Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/phramz/go-healthcheck

Simple health check utility written in Golang
https://github.com/phramz/go-healthcheck

Last synced: about 1 month ago
JSON representation

Simple health check utility written in Golang

Awesome Lists containing this project

README

        

Health Checker
==============

Tiny (< 9MB) CLI utility to perform health checks everywhere (container, local, etc)

## TL;DR

```shell
# via docker
$ docker run --rm gregthebunny/go-healthcheck probe '{{ .Assert.HTTPStatusCode .HTTP.Handler "GET" "https://github.com" nil 200 }}'

# ... or from source
$ make build

# check if github.com is up
$ build/bin/healthcheck probe '{{ .Assert.HTTPStatusCode .HTTP.Handler "GET" "https://github.com" nil 200 }}'
INFO [16:47:40] starting probe probe=p0 status=STARTED
INFO [16:47:40] finished probe probe=p0 status=PASS
INFO [16:47:40] 1 of 1 probes passed 👍
EXIT 0
```

## Usage

```
NAME:
healthcheck - HealthCheck Utility

USAGE:
healthcheck [global options] command [command options] [arguments...]

COMMANDS:
probe Performs a HTTP connection check
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--help, -h show help (default: false)
--log-level value Set the log output verbosity (default: "info") [$HC_DEBUG]
--no-fail If set failed checks won't cause the program to exit with an error code (default: false) [$HC_NO_FAIL]
--no-fail-affirmative If set the program won't exit with an error code as long as at least one probe passed (default: false) [$HC_NO_FAIL_AFFIRMATIVE]
--output If set rendered output will be printed to stdout (default: false) [$HC_OUTPUT]
--timeout value Maximum time in seconds after an unfinished probe will fail (default: 30) [$HC_TIMEOUT]
```

### Use it for your Docker images

```Dockerfile
# docker build -t hc-echo-example .
# docker run --name hc-echo-example --rm -p 5678:5678 hc-echo-example -text='my name is earl!'
# open http://localhost:5678
FROM hashicorp/http-echo

COPY --from=gregthebunny/go-healthcheck /bin/healthcheck /bin/healthcheck

ENV PROBE='{{ .Assert.HTTPBodyContains .HTTP.Handler "GET" "http://127.0.0.1:5678" nil "my name is earl!" }}'
HEALTHCHECK --start-period=10s --retries=3 --timeout=10s --interval=10s \
CMD ["/bin/healthcheck", "probe", "$PROBE"]

```

Now build and run:
```shell
$ docker build -t hc-echo-example .
$ docker run --name hc-echo-example --rm -p 5678:5678 hc-echo-example -text='my name is earl!'
```
`docker inspect --format "{{json .State.Health }}" hc-echo-example | jq`
```json
{
"Status": "healthy",
"FailingStreak": 0,
"Log": [
{
"Start": "2022-06-30T16:45:01.876566358Z",
"End": "2022-06-30T16:45:01.963092081Z",
"ExitCode": 0,
"Output": "time=\"16:45:01\" level=info msg=\"starting probe\" probe=p0 status=STARTED\ntime=\"16:45:01\" level=info msg=\"finished probe\" probe=p0 status=PASS\ntime=\"16:45:01\" level=info msg=\"1 of 1 probes passed 👍\"\n"
},
{
"Start": "2022-06-30T16:45:11.970180983Z",
"End": "2022-06-30T16:45:12.036572081Z",
"ExitCode": 0,
"Output": "time=\"16:45:12\" level=info msg=\"starting probe\" probe=p0 status=STARTED\ntime=\"16:45:12\" level=info msg=\"finished probe\" probe=p0 status=PASS\ntime=\"16:45:12\" level=info msg=\"1 of 1 probes passed 👍\"\n"
}
]
}
```
```shell
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f73899dc2b6c hc-echo-example "/http-echo '-text=m…" 2 minutes ago Up 2 minutes (healthy) 0.0.0.0:5678->5678/tcp hc-echo-example
```
### Examples

```shell
# play with env vars
$ MY_NAME=Earl ./healthcheck probe '{{ .Assert.Equal "My name is Earl!" ("My name is $MY_NAME!"|expandenv) }}'
INFO [16:19:52] starting probe probe=p0 status=STARTED
INFO [16:19:52] finished probe probe=p0 status=PASS
INFO [16:19:52] 1 of 1 probes passed 👍
EXIT 0

# run multiple probes
$ MY_NAME=Earl ./healthcheck probe '{{ .Assert.Equal "Me llamo Earl!" ("My name is $MY_NAME!"|expandenv) }}' \
'{{ .Assert.Equal "My name is Earl!" ("My name is $MY_NAME!"|expandenv) }}'
INFO [16:41:53] starting probe probe=p0 status=STARTED
WARNING[16:41:53]

Error: Not equal:
expected: "Me llamo Earl!"
actual : "My name is Earl!"

Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-Me llamo Earl!
+My name is Earl! probe=p0
WARNING[16:41:53] finished probe probe=p0 status=FAIL
INFO [16:41:53] starting probe probe=p1 status=STARTED
INFO [16:41:53] finished probe probe=p1 status=PASS
ERROR [16:41:53] 1 of 2 probes failed 😭
FAIL
EXIT 1
```

### Probes

Probes are basically go-templates (see "https://pkg.go.dev/text/template" to learn how utilize them) where you can
perform assertions on static or dynamic values

The renderer comes with the Sprig extension to add some more convenience. See
"http://masterminds.github.io/sprig/" for documentation and the sources on Github (https://github.com/Masterminds/sprig)

Here are some examples on how sprig can help you:

#### Environment variables

```bash
export HTTP_PORT=8080 healthcheck probe '{{ .Assert.Equal "http://localhost:8080" ("http://localhost:$HTTP_PORT"|expandenv) }}'
export HTTP_URL=http://localhost:8080 healthcheck probe '{{ .Assert.Equal "http://localhost:8080" ("HTTP_URL"|env) }}'
```

### Assertions

Most assertions available in the probes are provided by Testify (see https://github.com/stretchr/testify).
Have a look at the API Doc to see detailed information about it:
https://pkg.go.dev/github.com/stretchr/[email protected]/assert#Assertions

Here are some examples on how you can use assertions in probes:
#### Basics

```gotemplate
{{ .Assert.True false }}
{{ .Assert.Equal 200 (.HTTP.Request "GET" "http://localhost:8080").StatusCode }}
{{ .Assert.Regexp "^start"|regexp "its not starting" }}
{{ .Assert.NotRegexp (call .Regexp "^start") "its not starting" }}
```

#### HTTP

```gotemplate
{{ .Assert.HTTPStatusCode .HTTP.Handler "GET" "http://google.com" nil }}
{{ .Assert.HTTPError .HTTP.Handler "GET" "http://localhost:8080" nil }}
{{ .Assert.HTTPSuccess .HTTP.Handler "GET" "http://localhost:8080" nil }}
{{ .Assert.HTTPBodyContains .HTTP.Handler "GET" "http://localhost:8080" nil "hello world" }}
{{ .Assert.HTTPBodyNotContains .HTTP.Handler "GET" "http://localhost:8080" nil "hello world" }}
```

## Credits

This tool is base on multiple awesome open source libraries shout-outs to:
* https://github.com/stretchr/testify
* https://github.com/Masterminds/sprig
* https://github.com/urfave/cli

## License

```
MIT License

Copyright (c) 2022 Maximilian Reichel

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.
```