An easy to use, extensible health check library for Go applications.

Build Status Go Report Card GoDoc

Try browsing the code on Sourcegraph!

Go Health Check

An easy to use, extensible health check library for Go applications.

Table of Contents

Example

package main

import (
    "net/http"
    "database/sql"
    "time"

    "github.com/dimiro1/health"
    "github.com/dimiro1/health/url"
    "github.com/dimiro1/health/db"
    "github.com/dimiro1/health/redis"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    database, _ := sql.Open("mysql", "/")
	mysql := db.NewMySQLChecker(database)
    timeout := 5 * time.Second
    
    companies := health.NewCompositeChecker()
    companies.AddChecker("Microsoft", url.NewChecker("https://www.microsoft.com/"))
    companies.AddChecker("Oracle", url.NewChecker("https://www.oracle.com/"))
    companies.AddChecker("Google", url.NewChecker("https://www.google.com/"))

    handler := health.NewHandler()
    handler.AddChecker("Go", url.NewCheckerWithTimeout("https://golang.org/", timeout))
    handler.AddChecker("Big Companies", companies)
    handler.AddChecker("MySQL", mysql)
    handler.AddChecker("Redis", redis.NewChecker("tcp", ":6379"))

    http.Handle("/health/", handler)
    http.ListenAndServe(":8080", nil)
}
$ curl localhost:8080/health/

If everything is ok the server must respond with HTTP Status 200 OK and have following json in the body.

{
    "Big Companies": {
        "Google": {
            "code": 200,
            "status": "UP"
        },
        "Microsoft": {
            "code": 200,
            "status": "UP"
        },
        "Oracle": {
            "code": 200,
            "status": "UP"
        },
        "status": "UP"
    },
    "Go": {
        "code": 200,
        "status": "UP"
    },
    "MySQL": {
        "status": "UP",
        "version": "10.1.9-MariaDB"
    },
    "Redis": {
        "status": "UP",
        "version": "3.0.5"
    },
    "status": "UP"
}

The server responds with HTTP Status 503 Service Unavailable if the ckeck is Down and the json response could be something like this.

{
    "Big Companies": {
        "Google": {
            "code": 200,
            "status": "UP"
        },
        "Microsoft": {
            "code": 200,
            "status": "UP"
        },
        "Oracle": {
            "code": 200,
            "status": "UP"
        },
        "status": "UP"
    },
    "Go": {
        "code": 200,
        "status": "UP"
    },
    "MySQL": {
        "status": "DOWN",
        "error": "Error 1044: Access denied for user ''@'localhost' to database 'invalid-database'",
    },
    "Redis": {
        "status": "UP",
        "version": "3.0.5"
    },
    "status": "DOWN"
}

Motivation

It is very important to verify the status of your system, not only the system itself, but all its dependencies, If your system is not Up you can easily know what is the cause of the problem only looking the health check.

Also it serves as a kind of basic integration test between the systems.

Inspiration

I took a lot of ideas from the spring framework.

Installation

This package is a go getable package.

$ go get github.com/dimiro1/health

API

The API is stable and I do not have any plans to break compatibility, but I recommend you to vendor this dependency in your project, as it is a good practice.

Testing

You have to install the test dependencies.

$ go get gopkg.in/DATA-DOG/go-sqlmock.v1
$ go get github.com/rafaeljusto/redigomock

or you can go get this package with the -t flag

go get -t github.com/dimiro1/health

Implementing custom checkers

The key interface is health.Checker, you only have to implement a type that satisfies that interface.

type Checker interface {
	Check() Health
}

Here is an example of Disk Space usage (unix only).

package main

import (
    "syscall"
    "os"
)

type DiskSpaceChecker struct {
	Dir       string
	Threshold uint64
}

func NewDiskSpaceChecker(dir string, threshold uint64) DiskSpaceChecker {
	return DiskSpaceChecker{Dir: dir, Threshold: threshold}
}

func (d DiskSpaceChecker) Check() health.Health {
	health := health.NewHealth()

	var stat syscall.Statfs_t

	wd, err := os.Getwd()

	if err != nil {
        health.Down().AddInfo("error", err.Error()) // Why the check is Down
        return health
	}

	syscall.Statfs(wd, &stat)

	diskFreeInBytes := stat.Bavail * uint64(stat.Bsize)

	if diskFreeInBytes < d.Threshold {
		health.Down()
	} else {
        health.Up()
    }

    health.
        AddInfo("free", diskFreeInBytes).
        AddInfo("threshold", d.Threshold)

	return health
}

Important

The status key in the json has priority over a status key added by a Checker, so if some checker adds a status key to the json, it will not be rendered

Implemented health check indicators

Health Description Package
url.Checker Check the connection with some URL https://github.com/dimiro1/health/tree/master/url
db.Checker Check the connection with the database https://github.com/dimiro1/health/tree/master/db
redis.Checker Check the connection with the redis https://github.com/dimiro1/health/tree/master/redis

LICENSE

The MIT License (MIT)

Copyright (c) 2016 Claudemiro

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Owner
Claudemiro
@golang, @python developer, but can work well with Java and @nodejs.
Claudemiro
Comments
  • Give Status its own type

    Give Status its own type

    Hey,

    this is more of a suggestion than an issue. I think it would be helpful, to define a type for the Status property of the Health struct. This way, you can automatically check, if a checker returned an up or down state.

    Currently it is checked by comparing the value of Status to "up" or "down" (strings). A custom checker does not have to use those strings. So a custom checker may say "online" and it would return false on IsUp().

    This is a minor detail and you probably won't run into it, as checkers usually will use the Up() and Down() methods to alter the state of the Health struct. But in my opinion it would be cleaner to use a custom type and consts. Like

    type HealthStatus int
    
    const (
        UP HealthStatus = iota
        DOWN
        OUT_OF_SERVICE
        UNKNOWN
    )
    
    type Health struct {
        Status HealthStatus 
        Info   map[string]interface{}
    }
    
  • Me Info its own sub node when marshaling

    Me Info its own sub node when marshaling

    Currently all keys of the Info map are marshaled on the same level as the status. So if someone adds a "status" entry to the Info map, it will overwrite the actual status.

    Maybe this is intentional but I see a great danger here that a custom checker will alter the json in an unintentional way.

  • Feature background checks

    Feature background checks

    Added Start(interbval time.Duration) and Stop() to CompositeChecker Changed Check() to reply last background check result if background checking was enabled

  • How to integrate with golang/Gin framework

    How to integrate with golang/Gin framework

    Hello , This is pretty much simple and easy to understand the script. But I am using the Golang GIN framework for my microservices. Where I have a configuration file and some different Redis servers for which I need a simple health check service for Redis connection. Do you have any sample examples for the same? It will be really helpful to me if i get a custom example that explains how to use this lib in Gin Framework.

  • Bulk Setup of Entities

    Bulk Setup of Entities

    Have you given any thought to having the ability to do a bulk import / setup of entities to check? Just curious. ie

    {
        "websites": {
            "type": { 
                    "http": [
                        "http://golang.org",
                        "http://google.com",
                        "http://facebook.com",
                        "http://twitter.com",
                    ]
                }
            },
        "databases": {
            "type": {
                "mysql": [
                   "path.to.host1.local",
                   "path.to.host2.local",
                ]
            }
        },
        "services": {
            "type": {
                "tcp": [
                   "path.to.host1.loca:10009l",
                   "path.to.host2.local:8888",
                ]
            }
        }
    }
    

    Or something even simpler.

    Or even the ability to give the system a handler that expects a type for POST'ing in new data to look for?

    BTW, I love this library. Great work. I can't wait to start using it.

  • Parallel checks

    Parallel checks

    Right now the checks are executed one after another, would be interesting to execute them in parallel.

    See: https://github.com/dimiro1/health/blob/master/checker.go#L50

  • Using HEAD over GET in request

    Using HEAD over GET in request

    Hello,

    Would it be a better option to use a HTTP HEAD request instead of a GET request for the occasion where MANY urls are needed to be pinged for status information.

    This may be a quicker alternative to getting the whole document body.

    https://github.com/dimiro1/health/blob/master/url/checker.go#l23

  • Adding support to another Redis client

    Adding support to another Redis client

    Adding support to github.com/go-redis/redis Redis client

    There are no tests because the mock I found to this Redis client does not support the "INFO" command. I will try to add tests in another PR

Related tags
⛑ Gatus - Automated service health dashboard
⛑ Gatus - Automated service health dashboard

A service health dashboard in Go that is meant to be used as a docker image with a custom configuration file. I personally deploy it in my Kubernetes

Dec 31, 2022
Track health of various dependencies - golang

Background This package helps setup health check based on status of external dependencies. The idea is to add all external dependencies like database,

Dec 17, 2021
A Simple HTTP health checker for golang

patsch Permanently Assert Target Succeeds Check Health use cases used by kubernetes cluster admins to quickly identify faulty ingresses used by kubern

Feb 22, 2022
Render health ECG (electrocardiogram) animation
Render health ECG (electrocardiogram) animation

HealthECG Render health ECG (electrocardiogram) animation About This program shows how the health ECG animation was implemented in the original Reside

Jan 6, 2022
Antch, a fast, powerful and extensible web crawling & scraping framework for Go

Antch Antch, inspired by Scrapy. If you're familiar with scrapy, you can quickly get started. Antch is a fast, powerful and extensible web crawling &

Jan 6, 2023
Highly extensible, customizable application launcher and window switcher written in less than 300 lines of Golang and fyne
Highly extensible, customizable application launcher and window switcher written in less than 300 lines of Golang and fyne

golauncher A go application launcher A simple, highly extensible, customizable application launcher and window switcher written in less than 300 lines

Aug 21, 2022
An easy way to add useful startup banners into your Go applications
An easy way to add useful startup banners into your Go applications

Try browsing the code on Sourcegraph! Banner Add beautiful banners into your Go applications Table of Contents Motivation Usage API Command line flags

Jan 1, 2023
:sunglasses:Package captcha provides an easy to use, unopinionated API for captcha generation

Package captcha provides an easy to use, unopinionated API for captcha generation. Why another captcha generator? I want a simple and framework-indepe

Dec 28, 2022
An easy-to-use Map Reduce Go parallel-computing framework inspired by 2021 6.824 lab1. It supports multiple workers on a single machine right now.

MapReduce This is an easy-to-use Map Reduce Go framework inspired by 2021 6.824 lab1. Feature Multiple workers on single machine right now. Easy to pa

Dec 5, 2022
Hrple is an easy to use tool to help you create habits
Hrple is an easy to use tool to help you create habits

Hrple is an easy to use tool to help you create habits. This is loosely inspired by the book Atomic Habits by James Clear and techniques or frameworks like Kanban and the Pomodoro Technique.

Jun 2, 2022
Eye - An easy-use lib for event-driven pattern

?? Eye Eye 是一个简单易用的事件驱动模式库。 Read me in English ?? 功能特性 敬请期待。。。 历史版本的特性请查看 HISTOR

Jan 17, 2022
A fast and easy-to-use gutenberg book downloader

Gutenberg Downloader A brief description of what this project does and who it's for Usage download books Download all english books as epubs with imag

Jan 11, 2022
HyperKit: an easy-to-use bridge between LedFX, WLED, Bluetooth, HomeKit, and AirPlay2

HyperKit HyperKit is an easy-to-use bridge between LedFX, WLED, Bluetooth, HomeKit, and AirPlay2. HyperKit Functionality: Custom HomeKit Menu Integrat

Aug 20, 2022
[Building]Use Go & Vue3 to build an easy blog

Go + Vue3 Study 环境安装 本地环境:Go 1.17 后端框架:Gin 注意Go在使用Go Module的话需要使用修改Go的代理 首先查看Go相关的环境变量 go env 修改Go代理 go env -w Go111MODULE=on go env -w GOPROXY=https:

Jan 25, 2022
A easy-to-use and lightweight Go RPC framwork

zrpc 一个简单易用的Go RPC框架 功能 负载均衡(一致性哈希,Round-Robin, 随机) 服务注册与发现 心跳功能 超时处理(调用超时,连接超时,处理超时) 支持TCP/HTTP网络协议 连接复用 同步/异步调用 支持gob/json序列化协议 简单用法 创建注册中心 l, _ :=

Oct 30, 2022
A test repo to demonstrate the current (go1.17.2) issue when trying to use retractA test repo to demonstrate the current (go1.17.2) issue when trying to use retract

test-go-mod-retract This is a test repo to demonstrate the current (go1.17.2) issue when trying to use retract in go.mod to retract a version in a non

Oct 16, 2021
A Github action to check if IDT could synthesize a given DNA sequence.

dna-is-synthesizable A github action to check if a part is synthesizable from a given Genbank file. dna-is-synthesizable is a Github Action that recei

Oct 28, 2021
Prometheus instrumentation library for Go applications

Prometheus Go client library This is the Go client library for Prometheus. It has two separate parts, one for instrumenting application code, and one

Jan 3, 2023
A simple Cron library for go that can execute closures or functions at varying intervals, from once a second to once a year on a specific date and time. Primarily for web applications and long running daemons.

Cron.go This is a simple library to handle scheduled tasks. Tasks can be run in a minimum delay of once a second--for which Cron isn't actually design

Dec 17, 2022