-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from dotse/rewrite
✍ Major rewrite
- Loading branch information
Showing
18 changed files
with
615 additions
and
302 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright © 2019 The Swedish Internet Foundation | ||
// | ||
// Distributed under the MIT License. (See accompanying LICENSE file or copy at | ||
// <https://opensource.org/licenses/MIT>.) | ||
|
||
package health | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCheck(t *testing.T) { | ||
var check Check | ||
|
||
assert.True(t, check.Good()) | ||
check.Status = StatusWarn | ||
assert.True(t, check.Good()) | ||
check.Status = StatusFail | ||
assert.False(t, check.Good()) | ||
|
||
check.SetObservedTime(123*time.Microsecond + 456*time.Nanosecond) | ||
|
||
check.AffectedEndpoints = []string{"https://example.test/1", "https://example.test/2"} | ||
check.Output = "test output" | ||
check.Links = []string{"https://example.test/about"} | ||
|
||
j, err := json.Marshal(check) | ||
assert.NoError(t, err) | ||
assert.JSONEq(t, ` | ||
{ | ||
"affectedEndpoints": [ "https://example.test/1", "https://example.test/2" ], | ||
"links": [ "https://example.test/about" ], | ||
"observedUnit": "ns", | ||
"observedValue": 123456, | ||
"output": "test output", | ||
"status": "fail" | ||
} | ||
`, string(j)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// Copyright © 2019 The Swedish Internet Foundation | ||
// | ||
// Distributed under the MIT License. (See accompanying LICENSE file or copy at | ||
// <https://opensource.org/licenses/MIT>.) | ||
|
||
package client | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"net/http" | ||
"os" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/go-http-utils/headers" | ||
|
||
"github.com/dotse/go-health" | ||
"github.com/dotse/go-health/server" | ||
) | ||
|
||
const ( | ||
// ErrExit is the exit code on failure. | ||
ErrExit = 1 | ||
|
||
timeout = 30 * time.Second | ||
) | ||
|
||
// Config contains configuration for the CheckHealth() function. | ||
type Config struct { | ||
// The hostname. Defaults to 127.0.0.1. | ||
Host string | ||
|
||
// The port number. Defaults to 9999. | ||
Port int | ||
|
||
// HTTP timeout. Defaults to 30 seconds. | ||
Timeout time.Duration | ||
} | ||
|
||
// CheckHealth gets a Response from an HTTP server. | ||
func CheckHealth(config Config) (*health.Response, error) { | ||
if config.Host == "" { | ||
config.Host = "127.0.0.1" | ||
} | ||
|
||
if config.Port == 0 { | ||
config.Port = server.Port | ||
} | ||
|
||
if config.Timeout == 0 { | ||
config.Timeout = timeout | ||
} | ||
|
||
var ( | ||
addr = fmt.Sprintf("http://%s/", net.JoinHostPort(config.Host, strconv.Itoa(config.Port))) | ||
client = http.Client{ | ||
Timeout: config.Timeout, | ||
} | ||
) | ||
|
||
req, err := http.NewRequest(http.MethodGet, addr, nil) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create HTTP request: %w", err) | ||
} | ||
|
||
req.Header.Add(headers.Accept, server.ContentType) | ||
|
||
httpResp, err := client.Do(req) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to send HTTP request: %w", err) | ||
} | ||
|
||
defer httpResp.Body.Close() // nolint: errcheck | ||
|
||
resp, err := health.ReadResponse(httpResp.Body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
// CheckHealthCommand is a utility for services that exits the current process | ||
// with 0 or 1 for a healthy or unhealthy state, respectively. | ||
func CheckHealthCommand() { | ||
resp, err := CheckHealth(Config{}) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error: %v", err) | ||
os.Exit(ErrExit) | ||
} | ||
|
||
_, _ = resp.Write(os.Stdout) | ||
|
||
if resp.Good() { | ||
os.Exit(0) | ||
} | ||
|
||
os.Exit(ErrExit) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright © 2019 The Swedish Internet Foundation | ||
// | ||
// Distributed under the MIT License. (See accompanying LICENSE file or copy at | ||
// <https://opensource.org/licenses/MIT>.) | ||
|
||
package client | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/dotse/go-health" | ||
"github.com/dotse/go-health/server" | ||
) | ||
|
||
func ExampleCheckHealth() { | ||
// The server can be started before registering… | ||
if err := server.Start(); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Set up a checker so that there’s something to report. | ||
health.RegisterFunc("example", func() []health.Check { | ||
return []health.Check{{ | ||
Status: health.StatusPass, | ||
Output: "all good", | ||
}} | ||
}) | ||
|
||
// …or after. (Subsequent Start()s do nothing.) | ||
if err := server.Start(); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Get the current health status of a server running at localhost. More | ||
// configuration is possible. | ||
resp, err := CheckHealth(Config{ | ||
Timeout: time.Minute, | ||
}) | ||
|
||
if resp == nil || err != nil { | ||
panic(err) | ||
} | ||
|
||
fmt.Printf( | ||
` | ||
resp.Status: %q | ||
resp.Checks["example"][0].Status: %q | ||
resp.Checks["example"][0].Output: %q | ||
err: %v | ||
`, | ||
resp.Status, | ||
resp.Checks["example"][0].Status, | ||
resp.Checks["example"][0].Output, | ||
err, | ||
) | ||
|
||
// Output: | ||
// resp.Status: "pass" | ||
// resp.Checks["example"][0].Status: "pass" | ||
// resp.Checks["example"][0].Output: "all good" | ||
// err: <nil> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.