mirror of
https://github.com/openziti/zrok.git
synced 2025-06-25 20:22:45 +02:00
Merge pull request #385 from openziti/v0.4_healthcheck
New Health Check Endpoint (#372)
This commit is contained in:
commit
5861a037be
@ -1,3 +1,7 @@
|
|||||||
|
# v0.4.5
|
||||||
|
|
||||||
|
FEATURE: New health check endpoint (`/health`), which verifies that the underlying SQL store and metrics repository (InfluxDB, if configured) are operating correctly (https://github.com/openziti/zrok/issues/372)
|
||||||
|
|
||||||
# v0.4.4
|
# v0.4.4
|
||||||
|
|
||||||
FIX: `zrok status`, `zrok enable`, `zrok config`, etc. were all causing a panic when used on systems that had no previous `~/.zrok` directory (https://github.com/openziti/zrok/issues/383)
|
FIX: `zrok status`, `zrok enable`, `zrok config`, etc. were all causing a panic when used on systems that had no previous `~/.zrok` directory (https://github.com/openziti/zrok/issues/383)
|
||||||
|
@ -128,6 +128,7 @@ func Run(inCfg *config.Config) error {
|
|||||||
defer func() { _ = server.Shutdown() }()
|
defer func() { _ = server.Shutdown() }()
|
||||||
server.Host = cfg.Endpoint.Host
|
server.Host = cfg.Endpoint.Host
|
||||||
server.Port = cfg.Endpoint.Port
|
server.Port = cfg.Endpoint.Port
|
||||||
|
rest_server_zrok.HealthCheck = HealthCheckHTTP
|
||||||
server.ConfigureAPI()
|
server.ConfigureAPI()
|
||||||
if err := server.Serve(); err != nil {
|
if err := server.Serve(); err != nil {
|
||||||
return errors.Wrap(err, "api server error")
|
return errors.Wrap(err, "api server error")
|
||||||
@ -135,3 +136,7 @@ func Run(inCfg *config.Config) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Store() *store.Store {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
62
controller/health.go
Normal file
62
controller/health.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HealthCheckHTTP(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
if err := healthCheckStore(w); err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := healthCheckMetrics(w); err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
w.Write([]byte("<html><body><h1>Healthy</h1></body></html>"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func healthCheckStore(w http.ResponseWriter) error {
|
||||||
|
trx, err := str.Begin()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "error starting transaction", http.StatusInternalServerError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = trx.Rollback()
|
||||||
|
}()
|
||||||
|
count := -1
|
||||||
|
if err := trx.QueryRowx("select count(0) from migrations").Scan(&count); err != nil {
|
||||||
|
http.Error(w, "error selecting migration count", http.StatusInternalServerError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("%d migrations", count)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func healthCheckMetrics(w http.ResponseWriter) error {
|
||||||
|
if cfg.Metrics != nil && cfg.Metrics.Influx != nil {
|
||||||
|
queryApi := idb.QueryAPI(cfg.Metrics.Influx.Org)
|
||||||
|
query := fmt.Sprintf("from(bucket: \"%v\")\n", cfg.Metrics.Influx.Bucket) +
|
||||||
|
fmt.Sprintf("|> range(start: -5s)\n") +
|
||||||
|
"|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" +
|
||||||
|
"|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" +
|
||||||
|
"|> filter(fn: (r) => r[\"namespace\"] == \"backend\")\n" +
|
||||||
|
"|> sum()"
|
||||||
|
result, err := queryApi.Query(context.Background(), query)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "error querying influx", http.StatusInternalServerError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
results := 0
|
||||||
|
for result.Next() {
|
||||||
|
results++
|
||||||
|
}
|
||||||
|
logrus.Debugf("%d results", results)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -13,6 +13,8 @@ import (
|
|||||||
"github.com/openziti/zrok/rest_server_zrok/operations"
|
"github.com/openziti/zrok/rest_server_zrok/operations"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var HealthCheck func(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
//go:generate swagger generate server --target ../../zrok --name Zrok --spec ../specs/zrok.yml --model-package rest_model_zrok --server-package rest_server_zrok --principal interface{} --exclude-main
|
//go:generate swagger generate server --target ../../zrok --name Zrok --spec ../specs/zrok.yml --model-package rest_model_zrok --server-package rest_server_zrok --principal interface{} --exclude-main
|
||||||
|
|
||||||
func configureFlags(api *operations.ZrokAPI) {
|
func configureFlags(api *operations.ZrokAPI) {
|
||||||
@ -53,6 +55,5 @@ func setupMiddlewares(handler http.Handler) http.Handler {
|
|||||||
// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
|
// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
|
||||||
// So this is a good place to plug in a panic handling middleware, logging and metrics.
|
// So this is a good place to plug in a panic handling middleware, logging and metrics.
|
||||||
func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||||
logrus.Infof("configuring")
|
return ui.Middleware(handler, HealthCheck)
|
||||||
return ui.StaticBuilder(handler)
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StaticBuilder(handler http.Handler) http.Handler {
|
func Middleware(handler http.Handler, healthCheck func(w http.ResponseWriter, r *http.Request)) http.Handler {
|
||||||
logrus.Infof("building")
|
logrus.Infof("building")
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if strings.HasPrefix(r.URL.Path, "/api/v1") {
|
if strings.HasPrefix(r.URL.Path, "/api/v1") {
|
||||||
@ -17,6 +17,10 @@ func StaticBuilder(handler http.Handler) http.Handler {
|
|||||||
handler.ServeHTTP(w, r)
|
handler.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(r.URL.Path, "/health") {
|
||||||
|
healthCheck(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
logrus.Debugf("directing '%v' to static handler", r.URL.Path)
|
logrus.Debugf("directing '%v' to static handler", r.URL.Path)
|
||||||
|
|
16
ui/package-lock.json
generated
16
ui/package-lock.json
generated
@ -6196,9 +6196,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001450",
|
"version": "1.0.30001519",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
|
||||||
"integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==",
|
"integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -6207,6 +6207,10 @@
|
|||||||
{
|
{
|
||||||
"type": "tidelift",
|
"type": "tidelift",
|
||||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -24270,9 +24274,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30001450",
|
"version": "1.0.30001519",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
|
||||||
"integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew=="
|
"integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg=="
|
||||||
},
|
},
|
||||||
"canvas-color-tracker": {
|
"canvas-color-tracker": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user