checkup

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 2, 2019 License: MIT Imports: 32 Imported by: 31

README

Checkup

GoDoc Sourcegraph

Checkup is distributed, lock-free, self-hosted health checks and status pages, written in Go.

It features an elegant, minimalistic CLI and an idiomatic Go library. They are completely interoperable and their configuration is beautifully symmetric.

Checkup was created by Matt Holt, author of the Caddy web server. It is maintained and sponsored by Sourcegraph. If you'd like to dive into the source, you can start here.

This tool is a work-in-progress. Please use liberally (with discretion) and report any bugs!

Intro

Checkup can be customized to check up on any of your sites or services at any time, from any infrastructure, using any storage provider of your choice (assuming an integration exists for your storage provider). The status page can be customized to your liking since you can do your checks however you want. The status page is also mobile-responsive.

Checkup currently supports these checkers:

  • HTTP
  • TCP (+TLS)
  • DNS
  • TLS

Checkup implements these storage providers:

  • Amazon S3
  • Local file system
  • GitHub
  • SQL (sqlite3 or PostgreSQL)

Checkup can even send notifications through your service of choice (if an integration exists).

How it Works

There are 3 components:

  1. Storage. You set up storage space for the results of the checks.

  2. Checks. You run checks on whatever endpoints you have as often as you want.

  3. Status Page. You host the status page. Caddy makes this super easy. The status page downloads recent check files from storage and renders the results client-side.

Quick Start

Download Checkup for your platform and put it in your PATH, or install from source:

$ go get -u github.com/sourcegraph/checkup/cmd/checkup

You'll need Go 1.8 or newer. Verify it's installed properly:

$ checkup --help

Then follow these instructions to get started quickly with Checkup.

Create your Checkup config

You can configure Checkup entirely with a simple JSON document. You should configure storage and at least one checker. Here's the basic outline:

{
	"checkers": [
		// checker configurations go here
	],

	"storage": {
		// storage configuration goes here
	},

	"notifier": {
		// notifier configuration goes here
	}
}

Save the checkup configuration file as checkup.json in your working directory.

We will show JSON samples below, to get you started. But please refer to the godoc for a comprehensive description of each type of checker, storage, and notifier you can configure!

Here are the configuration structures you can use, which are explained fully in the godoc. Only the required fields are shown, so consult the godoc for more.

HTTP Checkers

godoc: HTTPChecker

{
	"type": "http",
	"endpoint_name": "Example HTTP",
	"endpoint_url": "http://www.example.com"
	// for more fields, see the godoc
}
TCP Checkers

godoc: TCPChecker

{
	"type": "tcp",
	"endpoint_name": "Example TCP",
	"endpoint_url": "example.com:80"
}
DNS Checkers

godoc: DNSChecker

{
	"type": "dns",
	"endpoint_name": "Example of endpoint_url looking up host.example.com",
	"endpoint_url": "ns.example.com:53",
	"hostname_fqdn": "host.example.com"
}
TLS Checkers

godoc: TLSChecker

{
	"type": "tls",
	"endpoint_name": "Example TLS Protocol Check",
	"endpoint_url": "www.example.com:443"
}
Amazon S3 Storage

godoc: S3

{
	"provider": "s3",
	"access_key_id": "<yours>",
	"secret_access_key": "<yours>",
	"bucket": "<yours>",
	"region": "us-east-1"
}

S3 is the default storage provider assumed by the status page, so the only change needed for the status page is in the config.js file, with your public, read-only credentials.

File System Storage

godoc: FS

{
	"provider": "fs",
	"dir": "/path/to/your/check_files",
	"url": "http://127.0.0.1:2015/check_files"
}

Change index.html to load fs.js instead of s3.js:

- <script src="js/s3.js"></script>
+ <script src="js/fs.js"></script>

Then fill out config.js so the status page knows how to load your check files.

GitHub Storage

godoc: GitHub

{
	"provider": "github",
	"access_token": "some_api_access_token_with_repo_scope",
	"repository_owner": "owner",
	"repository_name": "repo",
	"committer_name": "Commiter Name",
	"committer_email": "you@yours.com",
	"branch": "gh-pages",
	"dir": "updates"
}

Where "dir" is a subdirectory within the repo to push all the check files. Setup instructions:

  1. Create a repository.
  2. Copy the contents of statuspage/ from this repo to the root of your new repo.
  3. Change index.html to pull in js/fs.js instead of js/s3.js:
- <script src="js/s3.js"></script>
+ <script src="js/fs.js"></script>
  1. Create updates/.gitkeep.
  2. Enable GitHub Pages in your settings for your desired branch.
SQL Storage (sqlite3/PostgreSQL)

godoc: SQL

Postgres or sqlite3 databases can be used as storage backends.

sqlite database file configuration:

{
	"provider": "sql",
	"sqlite_db_file": "/path/to/your/sqlite.db"
}

postgresql database file configuration:

{
	"provider": "sql",
	"postgresql": {
		"user": "postgres",
		"dbname": "dbname",
		"host": "localhost",
		"port": 5432,
		"password": "password",
		"sslmode": "disable"
	}
}

The SQL engine used depends on which one is configured.

For all database backends, the database must exist and a "checks" table should be created:

CREATE TABLE checks (name TEXT NOT NULL PRIMARY KEY, timestamp INT8, results TEXT);

Currently the status page does not support SQL storage.

Slack notifier

Enable notifications in Slack with this Notifier configuration:

{
	"name": "slack",
	"username": "username",
	"channel": "#channel-name",
	"webhook": "webhook-url"
}

Follow these instructions to create a webhook.

Setting up storage on S3

The easiest way to do this is to give an IAM user these two privileges (keep the credentials secret):

  • arn:aws:iam::aws:policy/IAMFullAccess
  • arn:aws:iam::aws:policy/AmazonS3FullAccess

Implicit Provisioning

If you give these permissions to the same user as with the credentials in your JSON config above, then you can simply run:

$ checkup provision

and checkup will read the config file and provision S3 for you. If the user is different, you may want to use explicit provisioning instead.

This command creates a new IAM user with read-only permission to S3 and also creates a new bucket just for your check files. The credentials of the new user are printed to your screen. Make note of the Public Access Key ID and Public Access Key! You won't be able to see them again.

IMPORTANT SECURITY NOTE: This new IAM user will have read-only permission to all S3 buckets in your AWS account, and its credentials will be visible to any visitor to your status page. If you do not want to grant visitors to your status page read access to all your S3 buckets, you need to modify this IAM user's permissions to scope its access to the Checkup bucket. If in doubt, restrict access to your status page to trusted visitors. It is recommended that you do NOT include ANY sensitive credentials on the machine running Checkup.

Explicit Provisioning

If you do not prefer implicit provisioning using your checkup.json file, do this instead. Export the information to environment variables and run the provisioning command:

$ export AWS_ACCESS_KEY_ID=...
$ export AWS_SECRET_ACCESS_KEY=...
$ export AWS_BUCKET_NAME=...
$ checkup provision s3

Manual Provisioning

If you'd rather do this manually, see the instructions on the wiki but keeping in mind the region must be US Standard.

Setting up the status page

In statuspage/js, use the contents of config_template.js to fill out config.js, which is used by the status page. This is where you specify how to access the storage system you just provisioned for check files.

The status page can be served over HTTPS by running caddy -host status.mysite.com on the command line. (You can use getcaddy.com to install Caddy.)

As you perform checks, the status page will update every so often with the latest results. Only checks that are stored will appear on the status page.

Performing checks

You can run checks many different ways: cron, AWS Lambda, or a time.Ticker in your own Go program, to name a few. Checks should be run on a regular basis. How often you run checks depends on your requirements and how much time you render on the status page.

For example, if you run checks every 10 minutes, showing the last 24 hours on the status page will require 144 check files to be downloaded on each page load. You can distribute your checks to help avoid localized network problems, but this multiplies the number of files by the number of nodes you run checks on, so keep that in mind.

Performing checks with the checkup command is very easy.

Just cd to the folder with your checkup.json from earlier, and checkup will automatically use it:

$ checkup

The vanilla checkup command runs a single check and prints the results to your screen, but does not save them to storage for your status page.

To store the results instead, use --store:

$ checkup --store

If you want Checkup to loop forever and perform checks and store them on a regular interval, use this:

$ checkup every 10m

And replace the duration with your own preference. In addition to the regular time.ParseDuration() formats, you can use shortcuts like second, minute, hour, day, or week.

You can also get some help using the -h option for any command or subcommand.

Posting status messages

Site reliability engineers should post messages when there are incidents or other news relevant for a status page. This is also very easy:

$ checkup message --about=Example "Oops. We're trying to fix the problem. Stay tuned."

This stores a check file with your message attached to the result for a check named "Example" which you configured in checkup.json earlier.

Doing all that, but with Go

Checkup is as easy to use in a Go program as it is on the command line.

Using Go to set up storage on S3

First, create an IAM user with credentials as described in the section above.

Then go get github.com/sourcegraph/checkup and import it.

Then replace ACCESS_KEY_ID and SECRET_ACCESS_KEY below with the actual values for that user. Keep those secret. You'll also replace BUCKET_NAME with the unique bucket name to store your check files:

storage := checkup.S3{
	AccessKeyID:     "ACCESS_KEY_ID",
	SecretAccessKey: "SECRET_ACCESS_KEY",
	Bucket:          "BUCKET_NAME",
}
info, err := storage.Provision()
if err != nil {
	log.Fatal(err)
}
fmt.Println(info) // don't lose this output!

This method creates a new IAM user with read-only permission to S3 and also creates a new bucket just for your check files. The credentials of the new user are printed to your screen. Make note of the PublicAccessKeyID and PublicAccessKey! You won't be able to see them again.

Using Go to perform checks

First, go get github.com/sourcegraph/checkup and import it. Then configure it:

c := checkup.Checkup{
	Checkers: []checkup.Checker{
		checkup.HTTPChecker{Name: "Example (HTTP)", URL: "http://www.example.com", Attempts: 5},
		checkup.HTTPChecker{Name: "Example (HTTPS)", URL: "https://www.example.com", Attempts: 5},
		checkup.TCPChecker{Name:  "Example (TCP)", URL:  "www.example.com:80", Attempts: 5},
		checkup.TCPChecker{Name:  "Example (TCP SSL)", URL:  "www.example.com:443", Attempts: 5, TLSEnabled: true},
		checkup.TCPChecker{Name:  "Example (TCP SSL, self-signed certificate)", URL:  "www.example.com:443", Attempts: 5, TLSEnabled: true, TLSCAFile: "testdata/ca.pem"},
		checkup.TCPChecker{Name:  "Example (TCP SSL, validation disabled)", URL:  "www.example.com:8443", Attempts: 5, TLSEnabled: true, TLSSkipVerify: true},
		checkup.DNSChecker{Name:  "Example DNS test of ns.example.com:53 looking up host.example.com", URL:  "ns.example.com:53", Host: "host.example.com", Attempts: 5},
	},
	Storage: checkup.S3{
		AccessKeyID:     "<yours>",
		SecretAccessKey: "<yours>",
		Bucket:          "<yours>",
		Region:          "us-east-1",
		CheckExpiry:     24 * time.Hour * 7,
	},
}

This sample checks 2 endpoints (HTTP and HTTPS). Each check consists of 5 attempts so as to smooth out the final results a bit. We will store results on S3. Notice the CheckExpiry value. The checkup.S3 type is also checkup.Maintainer type, which means it can maintain itself and purge any status checks older than CheckExpiry. We chose 7 days.

Then, to run checks every 10 minutes:

c.CheckAndStoreEvery(10 * time.Minute)
select {}

CheckAndStoreEvery() returns a time.Ticker that you can stop, but in this case we just want it to run forever, so we block forever using an empty select.

Using Go to post status messages

Simply perform a check, add the message to the corresponding result, and then store it:

results, err := c.Check()
if err != nil {
	// handle err
}

results[0].Message = "We're investigating connectivity issues."

err = c.Storage.Store(results)
if err != nil {
	// handle err
}

Of course, real status messages should be as descriptive as possible. You can use HTML in them.

Other topics

Getting notified when there are problems

Uh oh, having some fires? 🔥 You can create a type that implements checkup.Notifier. Checkup will invoke Notify() after every check, where you can evaluate the results and decide if and how you want to send a notification or trigger some event.

Other kinds of checks or storage providers

You can implement your own Checker and Storage types. If it's general enough, feel free to submit a pull request so others can use it too!

Building Locally

Requires Go v1.10 or newer.

git clone git@github.com:sourcegraph/checkup.git
cd checkup/cmd/checkup/

# Install dependencies
go get -v -d

# Build binary
go build -v -ldflags '-s' -o ../../checkup

# Run tests
go test -race ../../

Building with Docker

Linux binary:

git clone git@github.com:sourcegraph/checkup.git
cd checkup
docker pull golang:latest
docker run --net=host --rm \
-v `pwd`:/project \
-w /project golang bash \
-c "cd cmd/checkup; go get -v -d; go build -v -ldflags '-s' -o ../../checkup"

This will create a checkup binary in the root project folder.

Documentation

Overview

Package checkup provides means for checking and reporting the status and performance of various endpoints in a distributed, lock-free, self-hosted fashion.

Index

Constants

View Source
const FilenameFormatString = "%d-check.json"

FilenameFormatString is the format string used by GenerateFilename to create a filename.

Variables

View Source
var DefaultConcurrentChecks = 5

DefaultConcurrentChecks is how many checks, at most, to perform concurrently.

View Source
var DefaultHTTPClient = &http.Client{
	Transport: &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 0,
		}).Dial,
		TLSHandshakeTimeout:   5 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		MaxIdleConnsPerHost:   1,
		DisableCompression:    true,
		DisableKeepAlives:     true,
		ResponseHeaderTimeout: 5 * time.Second,
	},
	CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
	},
	Timeout: 10 * time.Second,
}

DefaultHTTPClient is used when no other http.Client is specified on a HTTPChecker.

Functions

func DisableColor added in v1.0.0

func DisableColor()

DisableColor disables ANSI colors in the Result default string.

func GenerateFilename

func GenerateFilename() *string

GenerateFilename returns a filename that is ideal for storing the results file on a storage provider that relies on the filename for retrieval that is sorted by date/timeframe. It returns a string pointer to be used by the AWS SDK...

func Timestamp

func Timestamp() int64

Timestamp returns the UTC Unix timestamp in nanoseconds.

Types

type Attempt

type Attempt struct {
	RTT   time.Duration `json:"rtt"`
	Error string        `json:"error,omitempty"`
}

Attempt is an attempt to communicate with the endpoint.

type Attempts

type Attempts []Attempt

Attempts is a list of Attempt that can be sorted by RTT.

func (Attempts) Len

func (a Attempts) Len() int

func (Attempts) Less

func (a Attempts) Less(i, j int) bool

func (Attempts) Swap

func (a Attempts) Swap(i, j int)

type Checker

type Checker interface {
	Check() (Result, error)
}

Checker can create a Result.

type Checkup

type Checkup struct {
	// Checkers is the list of Checkers to use with
	// which to perform checks.
	Checkers []Checker `json:"checkers,omitempty"`

	// ConcurrentChecks is how many checks, at most, to
	// perform concurrently. Default is
	// DefaultConcurrentChecks.
	ConcurrentChecks int `json:"concurrent_checks,omitempty"`

	// Timestamp is the timestamp to force for all checks.
	// Useful if wanting to perform distributed check
	// "at the same time" even if they might actually
	// be a few milliseconds or seconds apart.
	Timestamp time.Time `json:"timestamp,omitempty"`

	// Storage is the storage mechanism for saving the
	// results of checks. Required if calling Store().
	// If Storage is also a Maintainer, its Maintain()
	// method will be called by c.CheckAndStore().
	Storage Storage `json:"storage,omitempty"`

	// Notifier is a notifier that will be passed the
	// results after checks from all checkers have
	// completed. Notifier may evaluate and choose to
	// send a notification of potential problems.
	Notifier Notifier `json:"notifier,omitempty"`
}

Checkup performs a routine checkup on endpoints or services.

func (Checkup) Check

func (c Checkup) Check() ([]Result, error)

Check performs the health checks. An error is only returned in the case of a misconfiguration or if any one of the Checkers returns an error.

func (Checkup) CheckAndStore

func (c Checkup) CheckAndStore() error

CheckAndStore performs health checks and immediately stores the results to the configured storage if there were no errors. Checks are not performed if c.Storage is nil. If c.Storage is also a Maintainer, Maintain() will be called if Store() is successful.

func (Checkup) CheckAndStoreEvery

func (c Checkup) CheckAndStoreEvery(interval time.Duration) *time.Ticker

CheckAndStoreEvery calls CheckAndStore every interval. It returns the ticker that it's using so you can stop it when you don't want it to run anymore. This function does NOT block (it runs the ticker in a goroutine). Any errors are written to the standard logger. It would not be wise to set an interval lower than the time it takes to perform the checks.

func (Checkup) MarshalJSON

func (c Checkup) MarshalJSON() ([]byte, error)

MarshalJSON marshals c into JSON with type information included on the interface values.

func (*Checkup) UnmarshalJSON

func (c *Checkup) UnmarshalJSON(b []byte) error

UnmarshalJSON unmarshales b into c. To succeed, it requires type information for the interface values.

type DNSChecker added in v0.2.0

type DNSChecker struct {
	// Name is the name of the endpoint.
	Name string `json:"endpoint_name"`
	// This is the name of the DNS server you are testing.
	URL string `json:"endpoint_url"`
	// This is the fqdn of the target server to query the DNS server for.
	Host string `json:"hostname_fqdn,omitempty"`
	// Timeout is the maximum time to wait for a
	// TCP connection to be established.
	Timeout time.Duration `json:"timeout,omitempty"`
	// ThresholdRTT is the maximum round trip time to
	// allow for a healthy endpoint. If non-zero and a
	// request takes longer than ThresholdRTT, the
	// endpoint will be considered unhealthy. Note that
	// this duration includes any in-between network
	// latency.
	ThresholdRTT time.Duration `json:"threshold_rtt,omitempty"`
	// Attempts is how many requests the client will
	// make to the endpoint in a single check.
	Attempts int `json:"attempts,omitempty"`
}

DNSChecker implements a Checker for TCP endpoints.

func (DNSChecker) Check added in v0.2.0

func (c DNSChecker) Check() (Result, error)

Check performs checks using c according to its configuration. An error is only returned if there is a configuration error.

type Errors

type Errors []error

Errors is an error type that concatenates multiple errors.

func (Errors) Empty

func (e Errors) Empty() bool

Empty returns whether e has any non-nil errors in it.

func (Errors) Error

func (e Errors) Error() string

Error returns a string containing all the errors in e.

type FS added in v0.2.0

type FS struct {
	// The path to the directory where check files will be stored.
	Dir string `json:"dir"`
	// The URL corresponding to fs.Dir.
	URL string `json:"url"`

	// Check files older than CheckExpiry will be
	// deleted on calls to Maintain(). If this is
	// the zero value, no old check files will be
	// deleted.
	CheckExpiry time.Duration `json:"check_expiry,omitempty"`
}

FS is a way to store checkup results on the local filesystem.

func (FS) Fetch added in v1.0.0

func (fs FS) Fetch(name string) ([]Result, error)

Fetch fetches results from filesystem for the specified index.

func (FS) GetIndex added in v1.0.0

func (fs FS) GetIndex() (map[string]int64, error)

GetIndex returns the index from filesystem.

func (FS) Maintain added in v0.2.0

func (fs FS) Maintain() error

Maintain deletes check files that are older than fs.CheckExpiry.

func (FS) Store added in v0.2.0

func (fs FS) Store(results []Result) error

Store stores results on filesystem according to the configuration in fs.

type GitHub added in v1.0.0

type GitHub struct {
	// AccessToken is the API token used to authenticate with GitHub (required).
	AccessToken string `json:"access_token"`

	// RepositoryOwner is the account which owns the repository on GitHub (required).
	// For https://github.com/octocat/kit, the owner is "octocat".
	RepositoryOwner string `json:"repository_owner"`

	// RepositoryName is the name of the repository on GitHub (required).
	// For https://github.com/octocat/kit, the name is "kit".
	RepositoryName string `json:"repository_name"`

	// CommitterName is the display name of the user corresponding to the AccessToken (required).
	// If the AccessToken is for user @octocat, then this might be "Mona Lisa," her name.
	CommitterName string `json:"committer_name"`

	// CommitterEmail is the email address of the user corresponding to the AccessToken (required).
	// If the AccessToken is for user @octocat, then this might be "mona@github.com".
	CommitterEmail string `json:"committer_email"`

	// Branch is the git branch to store the files to (required).
	Branch string `json:"branch"`

	// Dir is the subdirectory in the Git tree in which to store the files (required).
	// For example, to write to the directory "updates" in the Git repo, this should be "updates".
	Dir string `json:"dir"`

	// Check files older than CheckExpiry will be
	// deleted on calls to Maintain(). If this is
	// the zero value, no old check files will be
	// deleted.
	CheckExpiry time.Duration `json:"check_expiry,omitempty"`
	// contains filtered or unexported fields
}

GitHub is a way to store checkup results in a GitHub repository.

func (*GitHub) Fetch added in v1.0.0

func (gh *GitHub) Fetch(name string) ([]Result, error)

Fetch returns a checkup record -- Not tested!

func (*GitHub) GetIndex added in v1.0.0

func (gh *GitHub) GetIndex() (map[string]int64, error)

GetIndex returns the checkup index

func (*GitHub) Maintain added in v1.0.0

func (gh *GitHub) Maintain() error

Maintain deletes check files that are older than gh.CheckExpiry.

func (*GitHub) Store added in v1.0.0

func (gh *GitHub) Store(results []Result) error

Store stores results in the Git repo & updates the index.

type HTTPChecker

type HTTPChecker struct {
	// Name is the name of the endpoint.
	Name string `json:"endpoint_name"`

	// URL is the URL of the endpoint.
	URL string `json:"endpoint_url"`

	// UpStatus is the HTTP status code expected by
	// a healthy endpoint. Default is http.StatusOK.
	UpStatus int `json:"up_status,omitempty"`

	// ThresholdRTT is the maximum round trip time to
	// allow for a healthy endpoint. If non-zero and a
	// request takes longer than ThresholdRTT, the
	// endpoint will be considered unhealthy. Note that
	// this duration includes any in-between network
	// latency.
	ThresholdRTT time.Duration `json:"threshold_rtt,omitempty"`

	// MustContain is a string that the response body
	// must contain in order to be considered up.
	// NOTE: If set, the entire response body will
	// be consumed, which has the potential of using
	// lots of memory and slowing down checks if the
	// response body is large.
	MustContain string `json:"must_contain,omitempty"`

	// MustNotContain is a string that the response
	// body must NOT contain in order to be considered
	// up. If both MustContain and MustNotContain are
	// set, they are and-ed together. NOTE: If set,
	// the entire response body will be consumed, which
	// has the potential of using lots of memory and
	// slowing down checks if the response body is large.
	MustNotContain string `json:"must_not_contain,omitempty"`

	// Attempts is how many requests the client will
	// make to the endpoint in a single check.
	Attempts int `json:"attempts,omitempty"`

	// AttemptSpacing spaces out each attempt in a check
	// by this duration to avoid hitting a remote too
	// quickly in succession. By default, no waiting
	// occurs between attempts.
	AttemptSpacing time.Duration `json:"attempt_spacing,omitempty"`

	// Client is the http.Client with which to make
	// requests. If not set, DefaultHTTPClient is
	// used.
	Client *http.Client `json:"-"`

	// Headers contains headers to added to the request
	// that is sent for the check
	Headers http.Header `json:"headers,omitempty"`
}

HTTPChecker implements a Checker for HTTP endpoints.

func (HTTPChecker) Check

func (c HTTPChecker) Check() (Result, error)

Check performs checks using c according to its configuration. An error is only returned if there is a configuration error.

type Maintainer

type Maintainer interface {
	Maintain() error
}

Maintainer can maintain a store of results by deleting old check files that are no longer needed or performing other required tasks.

type Notifier

type Notifier interface {
	Notify([]Result) error
}

Notifier can notify ops or sysadmins of potential problems. A Notifier should keep state to avoid sending repeated notices more often than the admin would like.

type ProvisionInfo

type ProvisionInfo struct {
	// The ID of a user that was created for accessing checks.
	UserID string `json:"user_id"`

	// The username of a user that was created for accessing checks.
	Username string `json:"username"`

	// The ID or name of the ID/key used to access checks. Expect
	// this value to be made public. (It should have read-only
	// access to the checks.)
	PublicAccessKeyID string `json:"public_access_key_id"`

	// The "secret" associated with the PublicAccessKeyID, but
	// expect this value to be made public. (It should provide
	// read-only access to the checks.)
	PublicAccessKey string `json:"public_access_key"`
}

ProvisionInfo contains the results of provisioning a new storage facility for check files. Its values should be used by the status page in order to obtain read-only access to the check files.

func (ProvisionInfo) String

func (i ProvisionInfo) String() string

String returns the information in i in a human-readable format along with an important notice.

type Provisioner

type Provisioner interface {
	Provision() (ProvisionInfo, error)
}

Provisioner is a type of storage mechanism that can provision itself for use with checkup. Provisioning need only happen once and is merely a convenience so that the user can get up and running with their status page more quickly. Presumably, the info returned from Provision should be used on the status page side of things ot access the check files (like a key pair that is used for read-only access).

type Result

type Result struct {
	// Title is the title (or name) of the thing that was checked.
	// It should be unique, as it acts like an identifier to users.
	Title string `json:"title,omitempty"`

	// Endpoint is the URL/address/path/identifier/locator/whatever
	// of what was checked.
	Endpoint string `json:"endpoint,omitempty"`

	// Timestamp is when the check occurred; UTC UnixNano format.
	Timestamp int64 `json:"timestamp,omitempty"`

	// Times is a list of each individual check attempt.
	Times Attempts `json:"times,omitempty"`

	// ThresholdRTT is the maximum RTT that was tolerated before
	// considering performance to be degraded. Leave 0 if irrelevant.
	ThresholdRTT time.Duration `json:"threshold,omitempty"`

	// Healthy, Degraded, and Down contain the ultimate conclusion
	// about the endpoint. Exactly one of these should be true;
	// any more or less is a bug.
	Healthy  bool `json:"healthy,omitempty"`
	Degraded bool `json:"degraded,omitempty"`
	Down     bool `json:"down,omitempty"`

	// Notice contains a description of some condition of this
	// check that might have affected the result in some way.
	// For example, that the median RTT is above the threshold.
	Notice string `json:"notice,omitempty"`

	// Message is an optional message to show on the status page.
	// For example, what you're doing to fix a problem.
	Message string `json:"message,omitempty"`
}

Result is the result of a health check.

func (Result) ComputeStats

func (r Result) ComputeStats() Stats

ComputeStats computes basic statistics about r.

func (Result) Status

func (r Result) Status() StatusText

Status returns a text representation of the overall status indicated in r.

func (Result) String

func (r Result) String() string

String returns a human-readable rendering of r.

type S3

type S3 struct {
	AccessKeyID     string `json:"access_key_id"`
	SecretAccessKey string `json:"secret_access_key"`
	Region          string `json:"region,omitempty"`
	Bucket          string `json:"bucket"`

	// Check files older than CheckExpiry will be
	// deleted on calls to Maintain(). If this is
	// the zero value, no old check files will be
	// deleted.
	CheckExpiry time.Duration `json:"check_expiry,omitempty"`
}

S3 is a way to store checkup results in an S3 bucket.

func (S3) Maintain

func (s S3) Maintain() error

Maintain deletes check files that are older than s.CheckExpiry.

func (S3) Provision

func (s S3) Provision() (ProvisionInfo, error)

Provision creates a new IAM user in the account specified by s, and configures a bucket according to the values in s. The credentials in s must have the IAMFullAccess and AmazonS3FullAccess permissions in order to succeed.

The name of the created IAM user is "checkup-monitor-s3-public". It will have read-only permission to S3.

Provision need only be called once per status page (bucket), not once per endpoint.

func (S3) Store

func (s S3) Store(results []Result) error

Store stores results on S3 according to the configuration in s.

type SQL added in v1.0.0

type SQL struct {
	// SqliteDBFile is the sqlite3 DB where check results will be stored.
	SqliteDBFile string `json:"sqlite_db_file,omitempty"`

	// PostgreSQL contains the Postgres connection settings.
	PostgreSQL *struct {
		Host     string `json:"host,omitempty"`
		Port     int    `json:"port,omitempty"`
		User     string `json:"user"`
		Password string `json:"password,omitempty"`
		DBName   string `json:"dbname"`
		SSLMode  string `json:"sslmode,omitempty"`
	} `json:"postgresql"`

	// Check files older than CheckExpiry will be
	// deleted on calls to Maintain(). If this is
	// the zero value, no old check files will be
	// deleted.
	CheckExpiry time.Duration `json:"check_expiry,omitempty"`
}

SQL is a way to store checkup results in a SQL database.

func (SQL) Fetch added in v1.0.0

func (sql SQL) Fetch(name string) ([]Result, error)

Fetch fetches results of the check with given name.

func (SQL) GetIndex added in v1.0.0

func (sql SQL) GetIndex() (map[string]int64, error)

GetIndex returns the list of check results for the database.

func (SQL) Maintain added in v1.0.0

func (sql SQL) Maintain() error

Maintain deletes check files that are older than sql.CheckExpiry.

func (SQL) Store added in v1.0.0

func (sql SQL) Store(results []Result) error

Store stores results in the database.

type Slack added in v1.0.0

type Slack struct {
	Name     string `json:"name"`
	Username string `json:"username"`
	Channel  string `json:"channel"`
	Webhook  string `json:"webhook"`
}

Slack consist of all the sub components required to use Slack API

func (Slack) Notify added in v1.0.0

func (s Slack) Notify(results []Result) error

Notify implements notifier interface

func (Slack) Send added in v1.0.0

func (s Slack) Send(result Result) error

Send request via Slack API to create incident

type Stats

type Stats struct {
	Total  time.Duration `json:"total,omitempty"`
	Mean   time.Duration `json:"mean,omitempty"`
	Median time.Duration `json:"median,omitempty"`
	Min    time.Duration `json:"min,omitempty"`
	Max    time.Duration `json:"max,omitempty"`
}

Stats is a type that holds information about a Result, especially its various Attempts.

type StatusText

type StatusText string

StatusText is the textual representation of the result of a status check.

const (
	Healthy  StatusText = "healthy"
	Degraded StatusText = "degraded"
	Down     StatusText = "down"
	Unknown  StatusText = "unknown"
)

Text representations for the status of a check.

func (StatusText) PriorityOver

func (s StatusText) PriorityOver(other StatusText) bool

PriorityOver returns whether s has priority over other. For example, a Down status has priority over Degraded.

type Storage

type Storage interface {
	Store([]Result) error
}

Storage can store results.

type StorageReader added in v1.0.0

type StorageReader interface {
	// Fetch returns the contents of a check file.
	Fetch(checkFile string) ([]Result, error)
	// GetIndex returns the storage index, as a map where keys are check
	// result filenames and values are the associated check timestamps.
	GetIndex() (map[string]int64, error)
}

StorageReader can read results from the Storage.

type TCPChecker added in v0.2.0

type TCPChecker struct {
	// Name is the name of the endpoint.
	Name string `json:"endpoint_name"`

	// URL is the URL of the endpoint.
	URL string `json:"endpoint_url"`

	// TLSEnabled controls whether to enable TLS or not.
	// If set, TLS is enabled.
	TLSEnabled bool `json:"tls,omitempty"`

	// TLSSkipVerify controls whether to skip server TLS
	// certificat validation or not.
	TLSSkipVerify bool `json:"tls_skip_verify,omitempty"`

	// TLSCAFile is the Certificate Authority used
	// to validate the server TLS certificate.
	TLSCAFile string `json:"tls_ca_file,omitempty"`

	// Timeout is the maximum time to wait for a
	// TCP connection to be established.
	Timeout time.Duration `json:"timeout,omitempty"`

	// ThresholdRTT is the maximum round trip time to
	// allow for a healthy endpoint. If non-zero and a
	// request takes longer than ThresholdRTT, the
	// endpoint will be considered unhealthy. Note that
	// this duration includes any in-between network
	// latency.
	ThresholdRTT time.Duration `json:"threshold_rtt,omitempty"`

	// Attempts is how many requests the client will
	// make to the endpoint in a single check.
	Attempts int `json:"attempts,omitempty"`
}

TCPChecker implements a Checker for TCP endpoints.

func (TCPChecker) Check added in v0.2.0

func (c TCPChecker) Check() (Result, error)

Check performs checks using c according to its configuration. An error is only returned if there is a configuration error.

type TLSChecker added in v0.2.0

type TLSChecker struct {
	// Name is the name of the endpoint.
	Name string `json:"endpoint_name"`

	// URL is the host:port of the remote endpoint to check.
	URL string `json:"endpoint_url"`

	// Timeout is the maximum time to wait for a
	// TLS connection to be established.
	Timeout time.Duration `json:"timeout,omitempty"`

	// ThresholdRTT is the maximum round trip time to
	// allow for a healthy endpoint. If non-zero and a
	// request takes longer than ThresholdRTT, the
	// endpoint will be considered unhealthy. Note that
	// this duration includes any in-between network
	// latency.
	ThresholdRTT time.Duration `json:"threshold_rtt,omitempty"`

	// Attempts is how many requests the client will
	// make to the endpoint in a single check.
	Attempts int `json:"attempts,omitempty"`

	// CertExpiryThreshold is how close to expiration
	// the TLS certificate must be before declaring
	// a degraded status. Default is 14 days.
	CertExpiryThreshold time.Duration `json:"cert_expiry_threshold,omitempty"`

	// TrustedRoots is a list of PEM files to load as
	// trusted root CAs when connecting to TLS remotes.
	TrustedRoots []string `json:"trusted_roots,omitempty"`
	// contains filtered or unexported fields
}

TLSChecker implements a Checker for TLS endpoints.

TODO: Implement more checks on the certificate and TLS configuration.

  • Cipher suites
  • Protocol versions
  • OCSP stapling
  • Multiple SNIs
  • Other things that you might see at SSL Labs or other TLS health checks

func (TLSChecker) Check added in v0.2.0

func (c TLSChecker) Check() (Result, error)

Check performs checks using c according to its configuration. An error is only returned if there is a configuration error.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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