checkers

package
v2.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2023 License: MIT Imports: 13 Imported by: 7

README

checkers

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.

Built-in checkers

HTTP

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.

Redis

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.

SQL DB

The SQL DB checker has implementations for the following interfaces:

SQLConfig

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.

SQLPinger

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,
	})
SQLQueryer

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,
	})
SQLExecer

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

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.

Reachable

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.

Documentation

Index

Constants

View Source
const (
	// ReachableDDHealthErrors is the datadog name used when there is a failure in the reachable checker
	ReachableDDHealthErrors = "health.errors"
	// ReachableDefaultPort is the default port used if no port is defined in a reachable checker
	ReachableDefaultPort = "80"
	// ReachableDefaultNetwork is the default network used in the reachable checker
	ReachableDefaultNetwork = "tcp"
)

Variables

View Source
var (
	// ReachableDefaultTimeout is the default timeout used when reachable is checking the URL
	ReachableDefaultTimeout = time.Duration(3) * time.Second
)

Functions

func DefaultExecHandler

func DefaultExecHandler(result sql.Result) (bool, error)

DefaultExecHandler is the default SQLExecer result handler that assumes one row was affected in the passed query

func DefaultQueryHandler

func DefaultQueryHandler(rows *sql.Rows) (bool, error)

DefaultQueryHandler is the default SQLQueryer result handler that assumes one row was returned from the passed query

Types

type HTTP

type HTTP struct {
	Config *HTTPConfig
}

HTTP implements the "ICheckable" interface.

func NewHTTP

func NewHTTP(cfg *HTTPConfig) (*HTTP, error)

NewHTTP creates a new HTTP checker that can be used for ".AddCheck(s)".

func (*HTTP) Status

func (h *HTTP) Status() (interface{}, error)

Status is used for performing an HTTP check against a dependency; it satisfies the "ICheckable" interface.

type HTTPConfig

type HTTPConfig struct {
	URL        *url.URL      // Required
	Method     string        // Optional (default GET)
	Payload    interface{}   // Optional
	StatusCode int           // Optional (default 200)
	Expect     string        // Optional
	Client     *http.Client  // Optional
	Timeout    time.Duration // Optional (default 3s)
}

HTTPConfig is used for configuring an HTTP check. The only required field is `URL`.

"Method" is optional and defaults to `GET` if undefined.

"Payload" is optional and can accept `string`, `[]byte` or will attempt to marshal the input to JSON for use w/ `bytes.NewReader()`.

"StatusCode" is optional and defaults to `200`.

"Expect" is optional; if defined, operates as a basic "body should contain <string>".

"Client" is optional; if undefined, a new client will be created using "Timeout".

"Timeout" is optional and defaults to "3s".

type ReachableChecker

type ReachableChecker struct {
	// contains filtered or unexported fields
}

ReachableChecker checks that URL responds to a TCP request

func NewReachableChecker

func NewReachableChecker(cfg *ReachableConfig) (*ReachableChecker, error)

NewReachableChecker creates a new reachable health checker

func (*ReachableChecker) Status

func (r *ReachableChecker) Status() (interface{}, error)

Status checks if the endpoint is reachable

type ReachableConfig

type ReachableConfig struct {
	URL           *url.URL                    // Required
	Dialer        ReachableDialer             // Optional (default net.DialTimeout)
	Timeout       time.Duration               // Optional (default 3s)
	Network       string                      // Optional (default tcp)
	DatadogClient ReachableDatadogIncrementer // Optional
	DatadogTags   []string                    // Optional
}

ReachableConfig is used for configuring an HTTP check. The only required field is `URL`.

"Dialer" is optional and defaults to using net.DialTimeout.

"Timeout" is optional and defaults to "3s".

"Network" is optional and defaults to "tcp"; it should be one of "tcp", "tcp4", "tcp6", "unix", "unixpacket", "udp", "udp4", "udp6", "unixgram" or an IP transport. The IP transports are "ip", "ip4", or "ip6" followed by a colon and a literal protocol number or a protocol name, as in "ip:1" or "ip:icmp".

"DatadogClient" is optional; if defined metrics will be sent via statsd.

"DatadogTags" is optional; defines the tags that are passed to datadog when there is a failure

type ReachableDatadogIncrementer

type ReachableDatadogIncrementer interface {
	Incr(name string, tags []string, rate float64) error
}

ReachableDatadogIncrementer is any datadog client that has the Incr method for tracking metrics

type ReachableDialer

type ReachableDialer func(network, address string, timeout time.Duration) (net.Conn, error)

ReachableDialer is the signature for a function that checks if an address is reachable

type SQL

type SQL struct {
	Config *SQLConfig
}

SQL implements the "ICheckable" interface

func NewSQL

func NewSQL(cfg *SQLConfig) (*SQL, error)

NewSQL creates a new database checker that can be used for ".AddCheck(s)".

func (*SQL) Status

func (s *SQL) Status() (interface{}, error)

Status is used for performing a database ping against a dependency; it satisfies the "ICheckable" interface.

type SQLConfig

type SQLConfig struct {
	// Pinger is the value implementing SQLPinger
	Pinger SQLPinger

	// Queryer is the value implementing SQLQueryer
	Queryer SQLQueryer

	// Execer is the value implementing SQLExecer
	Execer SQLExecer

	// Query is the parameterized SQL query required
	// with both Queryer and Execer
	Query string

	// Params are the SQL query parameters, if any
	Params []interface{}

	// QueryerResultHandler handles the result of
	// the QueryContext function
	QueryerResultHandler SQLQueryerResultHandler

	// ExecerResultHandler handles the result of
	// the ExecContext function
	ExecerResultHandler SQLExecerResultHandler
}

SQLConfig is used for configuring a database check. One of the Pinger, Queryer, or Execer fields is required.

If Execer is set, it will take precedence over Queryer and Pinger, Execer implements the SQLExecer interface in this package. The sql.DB and sql.TX structs both implement this interface.

Note that if the Execer is set, then the ExecerResultHandler and Query values MUST also be set

If Queryer is set, it will take precedence over Pinger. SQLQueryer implements the SQLQueryer interface in this package. The sql.DB and sql.TX structs both implement this interface.

Note that if the Queryer is set, then the QueryerResultHandler and Query values MUST also be set

Pinger implements the SQLPinger interface in this package. The sql.DB struct implements this interface.

type SQLExecer

type SQLExecer interface {
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
}

SQLExecer is an interface that allows executing of queries in the database

type SQLExecerResultHandler

type SQLExecerResultHandler func(result sql.Result) (bool, error)

SQLExecerResultHandler is the BYO function to handle a database exec result

type SQLPinger

type SQLPinger interface {
	PingContext(ctx context.Context) error
}

SQLPinger is an interface that allows direct pinging of the database

type SQLQueryer

type SQLQueryer interface {
	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
}

SQLQueryer is an interface that allows querying of the database

type SQLQueryerResultHandler

type SQLQueryerResultHandler func(rows *sql.Rows) (bool, error)

SQLQueryerResultHandler is the BYO function to handle the result of an SQL SELECT query

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL