Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prometheus metric #57

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,3 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

39 changes: 39 additions & 0 deletions availability.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package health

// AvailabilityStatus expresses the availability of either
// a component or the whole system.
type AvailabilityStatus string

const (
// StatusUnknown holds the information that the availability
// status is not known, because not all checks were executed yet.
StatusUnknown AvailabilityStatus = "unknown"
// StatusUp holds the information that the system or a component
// is up and running.
StatusUp AvailabilityStatus = "up"
// StatusDown holds the information that the system or a component
// down and not available.
StatusDown AvailabilityStatus = "down"
)

func (s AvailabilityStatus) criticality() int {
switch s {
case StatusDown:
return 2
case StatusUnknown:
return 1
default:
return 0
}
}

func (s AvailabilityStatus) toPrometheusValue() float64 {
switch s {
case StatusDown:
return 0
case StatusUp:
return 1
default:
return 0
}
}
63 changes: 30 additions & 33 deletions check.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import (
"fmt"
"sync"
"time"

"github.com/prometheus/client_golang/prometheus"
)

type (
metricOptions struct {
namespace string
enabled bool
}
checkerConfig struct {
timeout time.Duration
checks map[string]*Check
Expand All @@ -17,14 +23,16 @@ type (
interceptors []Interceptor
detailsDisabled bool
autostartDisabled bool
metricOptions *metricOptions
}

defaultChecker struct {
started bool
mtx sync.Mutex
cfg checkerConfig
state CheckerState
endChans []chan *sync.WaitGroup
started bool
mtx sync.Mutex
cfg checkerConfig
state CheckerState
endChans []chan *sync.WaitGroup
promGauge *prometheus.GaugeVec
}

checkResult struct {
Expand Down Expand Up @@ -114,35 +122,8 @@ type (
// InterceptorFunc is an interceptor function that intercepts any call to
// a components health check function.
InterceptorFunc func(ctx context.Context, name string, state CheckState) CheckState

// AvailabilityStatus expresses the availability of either
// a component or the whole system.
AvailabilityStatus string
)

const (
// StatusUnknown holds the information that the availability
// status is not known, because not all checks were executed yet.
StatusUnknown AvailabilityStatus = "unknown"
// StatusUp holds the information that the system or a component
// is up and running.
StatusUp AvailabilityStatus = "up"
// StatusDown holds the information that the system or a component
// down and not available.
StatusDown AvailabilityStatus = "down"
)

func (s AvailabilityStatus) criticality() int {
switch s {
case StatusDown:
return 2
case StatusUnknown:
return 1
default:
return 0
}
}

func newDefaultChecker(cfg checkerConfig) *defaultChecker {
checkState := map[string]CheckState{}
for _, check := range cfg.checks {
Expand All @@ -154,7 +135,20 @@ func newDefaultChecker(cfg checkerConfig) *defaultChecker {
state: CheckerState{Status: StatusUnknown, CheckState: checkState},
endChans: []chan *sync.WaitGroup{},
}

if cfg.metricOptions != nil && cfg.metricOptions.enabled {
gaugeOpts := prometheus.GaugeOpts{
Name: "check_state",
Help: "status of each check",
}
if cfg.metricOptions.namespace != "" {
gaugeOpts.Namespace = cfg.metricOptions.namespace
}
resultGauge := prometheus.NewGaugeVec(
gaugeOpts, []string{"name"},
)
prometheus.MustRegister(resultGauge)
checker.promGauge = resultGauge
}
if !cfg.autostartDisabled {
checker.Start()
}
Expand Down Expand Up @@ -306,6 +300,9 @@ func (ck *defaultChecker) mapStateToCheckerResult() CheckerResult {
Error: toErrorDesc(checkState.Result, ck.cfg.maxErrMsgLen),
Timestamp: checkState.LastCheckedAt,
}
if ck.promGauge != nil {
ck.promGauge.WithLabelValues(c.Name).Set(float64(checkState.Status.toPrometheusValue()))
}
}
}

Expand Down
10 changes: 10 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,13 @@ func WithInterceptors(interceptors ...Interceptor) CheckerOption {
cfg.interceptors = interceptors
}
}

// WithMetrics will enable prometheus metrics
func WithMetrics(namespace string) CheckerOption {
return func(cfg *checkerConfig) {
cfg.metricOptions = &metricOptions{
enabled: true,
namespace: namespace,
}
}
}
19 changes: 18 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
module github.com/alexliesenfeld/health

go 1.13
go 1.19

require github.com/stretchr/testify v1.8.0

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading