Skip to content

Commit 466c8ae

Browse files
authored
feat(fxhealthcheck): Provided module (#34)
1 parent 00d281d commit 466c8ae

21 files changed

+811
-7
lines changed

.github/workflows/coverage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
- "trace"
3232
- "fxconfig"
3333
- "fxgenerate"
34+
- "fxhealthcheck"
3435
- "fxlog"
3536
- "fxmetrics"
3637
- "fxtrace"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: "fxhealthcheck-ci"
2+
3+
on:
4+
push:
5+
branches:
6+
- "feat**"
7+
- "fix**"
8+
- "hotfix**"
9+
- "chore**"
10+
paths:
11+
- "fxhealthcheck/**.go"
12+
- "fxhealthcheck/go.mod"
13+
- "fxhealthcheck/go.sum"
14+
pull_request:
15+
types:
16+
- opened
17+
- synchronize
18+
- reopened
19+
branches:
20+
- main
21+
paths:
22+
- "fxhealthcheck/**.go"
23+
- "fxhealthcheck/go.mod"
24+
- "fxhealthcheck/go.sum"
25+
26+
jobs:
27+
ci:
28+
uses: ./.github/workflows/common-ci.yml
29+
secrets: inherit
30+
with:
31+
module: "fxhealthcheck"

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ Yokai is using [Fx](https://github.com/uber-go/fx) for its plugin system.
2020

2121
Yokai's `Fx modules` are the plugins for your Yokai application.
2222

23-
| Fx Module | Description |
24-
|--------------------------|-------------------------------------------------------------------------|
25-
| [fxconfig](fxconfig) | Fx module for [config](config) |
26-
| [fxgenerate](fxgenerate) | Fx module for [generate](generate) |
27-
| [fxlog](fxlog) | Fx module for [log](log) |
28-
| [fxmetrics](fxmetrics) | Fx module for [prometheus](https://github.com/prometheus/client_golang) |
29-
| [fxtrace](fxtrace) | Fx module for [trace](trace) |
23+
| Fx Module | Description |
24+
|--------------------------------|-------------------------------------------------------------------------|
25+
| [fxconfig](fxconfig) | Fx module for [config](config) |
26+
| [fxgenerate](fxgenerate) | Fx module for [generate](generate) |
27+
| [fxhealthcheck](fxhealthcheck) | Fx module for [healthcheck](healthcheck) |
28+
| [fxlog](fxlog) | Fx module for [log](log) |
29+
| [fxmetrics](fxmetrics) | Fx module for [prometheus](https://github.com/prometheus/client_golang) |
30+
| [fxtrace](fxtrace) | Fx module for [trace](trace) |
3031

3132
They can also be used in any [Fx](https://github.com/uber-go/fx) based Go application.
3233

fxhealthcheck/.golangci.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
run:
2+
timeout: 5m
3+
concurrency: 8
4+
5+
linters:
6+
enable:
7+
- asasalint
8+
- asciicheck
9+
- bidichk
10+
- bodyclose
11+
- containedctx
12+
- contextcheck
13+
- cyclop
14+
- decorder
15+
- dogsled
16+
- dupl
17+
- durationcheck
18+
- errcheck
19+
- errchkjson
20+
- errname
21+
- errorlint
22+
- exhaustive
23+
- forbidigo
24+
- forcetypeassert
25+
- gocognit
26+
- goconst
27+
- gocritic
28+
- gocyclo
29+
- godot
30+
- godox
31+
- gofmt
32+
- goheader
33+
- gomoddirectives
34+
- gomodguard
35+
- goprintffuncname
36+
- gosec
37+
- gosimple
38+
- govet
39+
- grouper
40+
- importas
41+
- ineffassign
42+
- interfacebloat
43+
- logrlint
44+
- maintidx
45+
- makezero
46+
- misspell
47+
- nestif
48+
- nilerr
49+
- nilnil
50+
- nlreturn
51+
- nolintlint
52+
- nosprintfhostport
53+
- prealloc
54+
- predeclared
55+
- promlinter
56+
- reassign
57+
- staticcheck
58+
- tenv
59+
- thelper
60+
- tparallel
61+
- typecheck
62+
- unconvert
63+
- unparam
64+
- unused
65+
- usestdlibvars
66+
- whitespace

fxhealthcheck/README.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Fx Health Check Module
2+
3+
[![ci](https://github.com/ankorstore/yokai/actions/workflows/fxhealthcheck-ci.yml/badge.svg)](https://github.com/ankorstore/yokai/actions/workflows/fxhealthcheck-ci.yml)
4+
[![go report](https://goreportcard.com/badge/github.com/ankorstore/yokai/fxhealthcheck)](https://goreportcard.com/report/github.com/ankorstore/yokai/fxhealthcheck)
5+
[![codecov](https://codecov.io/gh/ankorstore/yokai/graph/badge.svg?token=ghUBlFsjhR&flag=fxhealthcheck)](https://app.codecov.io/gh/ankorstore/yokai/tree/main/fxhealthcheck)
6+
[![Deps](https://img.shields.io/badge/osi-deps-blue)](https://deps.dev/go/github.com%2Fankorstore%2Fyokai%2Ffxhealthcheck)
7+
[![PkgGoDev](https://pkg.go.dev/badge/github.com/ankorstore/yokai/fxhealthcheck)](https://pkg.go.dev/github.com/ankorstore/yokai/fxhealthcheck)
8+
9+
> [Fx](https://uber-go.github.io/fx/) module for [healthcheck](https://github.com/ankorstore/yokai/tree/main/healthcheck).
10+
11+
<!-- TOC -->
12+
13+
* [Installation](#installation)
14+
* [Documentation](#documentation)
15+
* [Loading](#loading)
16+
* [Registration](#registration)
17+
* [Override](#override)
18+
19+
<!-- TOC -->
20+
21+
## Installation
22+
23+
```shell
24+
go get github.com/ankorstore/yokai/fxhealthcheck
25+
```
26+
27+
## Documentation
28+
29+
### Loading
30+
31+
To load the module in your Fx application:
32+
33+
```go
34+
package main
35+
36+
import (
37+
"context"
38+
"fmt"
39+
40+
"github.com/ankorstore/yokai/fxhealthcheck"
41+
"github.com/ankorstore/yokai/healthcheck"
42+
"go.uber.org/fx"
43+
)
44+
45+
func main() {
46+
fx.New(
47+
fxhealthcheck.FxHealthcheckModule, // load the module
48+
fx.Invoke(func(checker *healthcheck.Checker) { // invoke the checker for liveness checks
49+
fmt.Printf("checker result: %v", checker.Check(context.Background(), healthcheck.Liveness))
50+
}),
51+
).Run()
52+
}
53+
```
54+
55+
### Registration
56+
57+
This module provides the possibility to register
58+
several [CheckerProbe](https://github.com/ankorstore/yokai/blob/main/healthcheck/probe.go) implementations, and organise
59+
them for `startup`, `liveness` and /
60+
or `readiness` [checks](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/).
61+
62+
They will be then collected and given by Fx to
63+
the [Checker](https://github.com/ankorstore/yokai/blob/main/healthcheck/checker.go), made available in the Fx container.
64+
65+
This is done via the `AsCheckerProbe()` function:
66+
67+
```go
68+
package main
69+
70+
import (
71+
"context"
72+
"fmt"
73+
74+
"github.com/ankorstore/yokai/fxhealthcheck"
75+
"github.com/ankorstore/yokai/healthcheck"
76+
"go.uber.org/fx"
77+
)
78+
79+
// example success probe
80+
type SuccessProbe struct{}
81+
82+
func NewSuccessProbe() *SuccessProbe {
83+
return &SuccessProbe{}
84+
}
85+
86+
func (p *SuccessProbe) Name() string {
87+
return "successProbe"
88+
}
89+
90+
func (p *SuccessProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult {
91+
return healthcheck.NewCheckerProbeResult(true, "some success")
92+
}
93+
94+
// example failure probe
95+
type FailureProbe struct{}
96+
97+
func NewFailureProbe() *FailureProbe {
98+
return &FailureProbe{}
99+
}
100+
101+
func (p *FailureProbe) Name() string {
102+
return "someProbe"
103+
}
104+
105+
func (p *FailureProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult {
106+
return healthcheck.NewCheckerProbeResult(false, "some failure")
107+
}
108+
109+
// usage
110+
func main() {
111+
fx.New(
112+
fxhealthcheck.FxHealthcheckModule, // load the module
113+
fx.Provide(
114+
fxhealthcheck.AsCheckerProbe(NewSuccessProbe), // register the SuccessProbe probe for startup, liveness and readiness checks
115+
fxhealthcheck.AsCheckerProbe(NewFailureProbe, healthcheck.Liveness), // register the FailureProbe probe for liveness checks only
116+
),
117+
fx.Invoke(func(checker *healthcheck.Checker) { // invoke the checker
118+
ctx := context.Background()
119+
120+
fmt.Printf("startup: %v", checker.Check(ctx, healthcheck.Startup).Success) // startup: true
121+
fmt.Printf("liveness: %v", checker.Check(ctx, healthcheck.Liveness).Success) // liveness: false
122+
fmt.Printf("readiness: %v", checker.Check(ctx, healthcheck.Readiness).Success) // readiness: true
123+
}),
124+
).Run()
125+
}
126+
```
127+
128+
### Override
129+
130+
By default, the `healthcheck.Checker` is created by
131+
the [DefaultCheckerFactory](https://github.com/ankorstore/yokai/blob/main/healthcheck/factory.go).
132+
133+
If needed, you can provide your own factory and override the module:
134+
135+
```go
136+
package main
137+
138+
import (
139+
"context"
140+
141+
"github.com/ankorstore/yokai/fxhealthcheck"
142+
"github.com/ankorstore/yokai/healthcheck"
143+
"go.uber.org/fx"
144+
)
145+
146+
type CustomCheckerFactory struct{}
147+
148+
func NewCustomCheckerFactory() healthcheck.CheckerFactory {
149+
return &CustomCheckerFactory{}
150+
}
151+
152+
func (f *CustomCheckerFactory) Create(options ...healthcheck.CheckerOption) (*healthcheck.Checker, error) {
153+
return &healthcheck.Checker{...}, nil
154+
}
155+
156+
func main() {
157+
fx.New(
158+
fxhealthcheck.FxHealthcheckModule, // load the module
159+
fx.Decorate(NewCustomCheckerFactory), // override the module with a custom factory
160+
fx.Invoke(func(checker *healthcheck.Checker) { // invoke the custom checker for readiness checks
161+
checker.Check(context.Background(), healthcheck.Readiness)
162+
}),
163+
).Run()
164+
}
165+
```

fxhealthcheck/define.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package fxhealthcheck
2+
3+
import "github.com/ankorstore/yokai/healthcheck"
4+
5+
// CheckerProbeDefinition is the interface for probes definitions.
6+
type CheckerProbeDefinition interface {
7+
ReturnType() string
8+
Kinds() []healthcheck.ProbeKind
9+
}
10+
11+
type checkerProbeDefinition struct {
12+
returnType string
13+
kinds []healthcheck.ProbeKind
14+
}
15+
16+
// NewCheckerProbeDefinition returns a new [CheckerProbeDefinition].
17+
func NewCheckerProbeDefinition(returnType string, kinds ...healthcheck.ProbeKind) CheckerProbeDefinition {
18+
return &checkerProbeDefinition{
19+
returnType: returnType,
20+
kinds: kinds,
21+
}
22+
}
23+
24+
// ReturnType returns the probe return type.
25+
func (c *checkerProbeDefinition) ReturnType() string {
26+
return c.returnType
27+
}
28+
29+
// Kinds returns the probe registration kinds.
30+
func (c *checkerProbeDefinition) Kinds() []healthcheck.ProbeKind {
31+
return c.kinds
32+
}

fxhealthcheck/define_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package fxhealthcheck_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/ankorstore/yokai/fxhealthcheck"
7+
"github.com/ankorstore/yokai/healthcheck"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestNewCheckerProbeDefinition(t *testing.T) {
12+
t.Parallel()
13+
14+
definition := fxhealthcheck.NewCheckerProbeDefinition("test", healthcheck.Liveness, healthcheck.Readiness)
15+
16+
assert.Implements(t, (*fxhealthcheck.CheckerProbeDefinition)(nil), definition)
17+
assert.Equal(t, "test", definition.ReturnType())
18+
assert.Equal(t, []healthcheck.ProbeKind{healthcheck.Liveness, healthcheck.Readiness}, definition.Kinds())
19+
}

fxhealthcheck/go.mod

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module github.com/ankorstore/yokai/fxhealthcheck
2+
3+
go 1.20
4+
5+
require (
6+
github.com/ankorstore/yokai/healthcheck v1.0.0
7+
github.com/stretchr/testify v1.8.4
8+
go.uber.org/fx v1.20.1
9+
)
10+
11+
require (
12+
github.com/davecgh/go-spew v1.1.1 // indirect
13+
github.com/pmezard/go-difflib v1.0.0 // indirect
14+
go.uber.org/atomic v1.7.0 // indirect
15+
go.uber.org/dig v1.17.0 // indirect
16+
go.uber.org/multierr v1.6.0 // indirect
17+
go.uber.org/zap v1.23.0 // indirect
18+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
19+
gopkg.in/yaml.v3 v3.0.1 // indirect
20+
)

0 commit comments

Comments
 (0)