Skip to content

feat(fxhealthcheck): Provided module #34

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

Merged
merged 1 commit into from
Jan 12, 2024
Merged
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: 1 addition & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
- "trace"
- "fxconfig"
- "fxgenerate"
- "fxhealthcheck"
- "fxlog"
- "fxmetrics"
- "fxtrace"
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/fxhealthcheck-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "fxhealthcheck-ci"

on:
push:
branches:
- "feat**"
- "fix**"
- "hotfix**"
- "chore**"
paths:
- "fxhealthcheck/**.go"
- "fxhealthcheck/go.mod"
- "fxhealthcheck/go.sum"
pull_request:
types:
- opened
- synchronize
- reopened
branches:
- main
paths:
- "fxhealthcheck/**.go"
- "fxhealthcheck/go.mod"
- "fxhealthcheck/go.sum"

jobs:
ci:
uses: ./.github/workflows/common-ci.yml
secrets: inherit
with:
module: "fxhealthcheck"
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ Yokai is using [Fx](https://github.com/uber-go/fx) for its plugin system.

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

| Fx Module | Description |
|--------------------------|-------------------------------------------------------------------------|
| [fxconfig](fxconfig) | Fx module for [config](config) |
| [fxgenerate](fxgenerate) | Fx module for [generate](generate) |
| [fxlog](fxlog) | Fx module for [log](log) |
| [fxmetrics](fxmetrics) | Fx module for [prometheus](https://github.com/prometheus/client_golang) |
| [fxtrace](fxtrace) | Fx module for [trace](trace) |
| Fx Module | Description |
|--------------------------------|-------------------------------------------------------------------------|
| [fxconfig](fxconfig) | Fx module for [config](config) |
| [fxgenerate](fxgenerate) | Fx module for [generate](generate) |
| [fxhealthcheck](fxhealthcheck) | Fx module for [healthcheck](healthcheck) |
| [fxlog](fxlog) | Fx module for [log](log) |
| [fxmetrics](fxmetrics) | Fx module for [prometheus](https://github.com/prometheus/client_golang) |
| [fxtrace](fxtrace) | Fx module for [trace](trace) |

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

Expand Down
66 changes: 66 additions & 0 deletions fxhealthcheck/.golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
run:
timeout: 5m
concurrency: 8

linters:
enable:
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- contextcheck
- cyclop
- decorder
- dogsled
- dupl
- durationcheck
- errcheck
- errchkjson
- errname
- errorlint
- exhaustive
- forbidigo
- forcetypeassert
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- gofmt
- goheader
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- gosimple
- govet
- grouper
- importas
- ineffassign
- interfacebloat
- logrlint
- maintidx
- makezero
- misspell
- nestif
- nilerr
- nilnil
- nlreturn
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- staticcheck
- tenv
- thelper
- tparallel
- typecheck
- unconvert
- unparam
- unused
- usestdlibvars
- whitespace
165 changes: 165 additions & 0 deletions fxhealthcheck/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Fx Health Check Module

[![ci](https://github.com/ankorstore/yokai/actions/workflows/fxhealthcheck-ci.yml/badge.svg)](https://github.com/ankorstore/yokai/actions/workflows/fxhealthcheck-ci.yml)
[![go report](https://goreportcard.com/badge/github.com/ankorstore/yokai/fxhealthcheck)](https://goreportcard.com/report/github.com/ankorstore/yokai/fxhealthcheck)
[![codecov](https://codecov.io/gh/ankorstore/yokai/graph/badge.svg?token=ghUBlFsjhR&flag=fxhealthcheck)](https://app.codecov.io/gh/ankorstore/yokai/tree/main/fxhealthcheck)
[![Deps](https://img.shields.io/badge/osi-deps-blue)](https://deps.dev/go/github.com%2Fankorstore%2Fyokai%2Ffxhealthcheck)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/ankorstore/yokai/fxhealthcheck)](https://pkg.go.dev/github.com/ankorstore/yokai/fxhealthcheck)

> [Fx](https://uber-go.github.io/fx/) module for [healthcheck](https://github.com/ankorstore/yokai/tree/main/healthcheck).

<!-- TOC -->

* [Installation](#installation)
* [Documentation](#documentation)
* [Loading](#loading)
* [Registration](#registration)
* [Override](#override)

<!-- TOC -->

## Installation

```shell
go get github.com/ankorstore/yokai/fxhealthcheck
```

## Documentation

### Loading

To load the module in your Fx application:

```go
package main

import (
"context"
"fmt"

"github.com/ankorstore/yokai/fxhealthcheck"
"github.com/ankorstore/yokai/healthcheck"
"go.uber.org/fx"
)

func main() {
fx.New(
fxhealthcheck.FxHealthcheckModule, // load the module
fx.Invoke(func(checker *healthcheck.Checker) { // invoke the checker for liveness checks
fmt.Printf("checker result: %v", checker.Check(context.Background(), healthcheck.Liveness))
}),
).Run()
}
```

### Registration

This module provides the possibility to register
several [CheckerProbe](https://github.com/ankorstore/yokai/blob/main/healthcheck/probe.go) implementations, and organise
them for `startup`, `liveness` and /
or `readiness` [checks](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/).

They will be then collected and given by Fx to
the [Checker](https://github.com/ankorstore/yokai/blob/main/healthcheck/checker.go), made available in the Fx container.

This is done via the `AsCheckerProbe()` function:

```go
package main

import (
"context"
"fmt"

"github.com/ankorstore/yokai/fxhealthcheck"
"github.com/ankorstore/yokai/healthcheck"
"go.uber.org/fx"
)

// example success probe
type SuccessProbe struct{}

func NewSuccessProbe() *SuccessProbe {
return &SuccessProbe{}
}

func (p *SuccessProbe) Name() string {
return "successProbe"
}

func (p *SuccessProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult {
return healthcheck.NewCheckerProbeResult(true, "some success")
}

// example failure probe
type FailureProbe struct{}

func NewFailureProbe() *FailureProbe {
return &FailureProbe{}
}

func (p *FailureProbe) Name() string {
return "someProbe"
}

func (p *FailureProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult {
return healthcheck.NewCheckerProbeResult(false, "some failure")
}

// usage
func main() {
fx.New(
fxhealthcheck.FxHealthcheckModule, // load the module
fx.Provide(
fxhealthcheck.AsCheckerProbe(NewSuccessProbe), // register the SuccessProbe probe for startup, liveness and readiness checks
fxhealthcheck.AsCheckerProbe(NewFailureProbe, healthcheck.Liveness), // register the FailureProbe probe for liveness checks only
),
fx.Invoke(func(checker *healthcheck.Checker) { // invoke the checker
ctx := context.Background()

fmt.Printf("startup: %v", checker.Check(ctx, healthcheck.Startup).Success) // startup: true
fmt.Printf("liveness: %v", checker.Check(ctx, healthcheck.Liveness).Success) // liveness: false
fmt.Printf("readiness: %v", checker.Check(ctx, healthcheck.Readiness).Success) // readiness: true
}),
).Run()
}
```

### Override

By default, the `healthcheck.Checker` is created by
the [DefaultCheckerFactory](https://github.com/ankorstore/yokai/blob/main/healthcheck/factory.go).

If needed, you can provide your own factory and override the module:

```go
package main

import (
"context"

"github.com/ankorstore/yokai/fxhealthcheck"
"github.com/ankorstore/yokai/healthcheck"
"go.uber.org/fx"
)

type CustomCheckerFactory struct{}

func NewCustomCheckerFactory() healthcheck.CheckerFactory {
return &CustomCheckerFactory{}
}

func (f *CustomCheckerFactory) Create(options ...healthcheck.CheckerOption) (*healthcheck.Checker, error) {
return &healthcheck.Checker{...}, nil
}

func main() {
fx.New(
fxhealthcheck.FxHealthcheckModule, // load the module
fx.Decorate(NewCustomCheckerFactory), // override the module with a custom factory
fx.Invoke(func(checker *healthcheck.Checker) { // invoke the custom checker for readiness checks
checker.Check(context.Background(), healthcheck.Readiness)
}),
).Run()
}
```
32 changes: 32 additions & 0 deletions fxhealthcheck/define.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package fxhealthcheck

import "github.com/ankorstore/yokai/healthcheck"

// CheckerProbeDefinition is the interface for probes definitions.
type CheckerProbeDefinition interface {
ReturnType() string
Kinds() []healthcheck.ProbeKind
}

type checkerProbeDefinition struct {
returnType string
kinds []healthcheck.ProbeKind
}

// NewCheckerProbeDefinition returns a new [CheckerProbeDefinition].
func NewCheckerProbeDefinition(returnType string, kinds ...healthcheck.ProbeKind) CheckerProbeDefinition {
return &checkerProbeDefinition{
returnType: returnType,
kinds: kinds,
}
}

// ReturnType returns the probe return type.
func (c *checkerProbeDefinition) ReturnType() string {
return c.returnType
}

// Kinds returns the probe registration kinds.
func (c *checkerProbeDefinition) Kinds() []healthcheck.ProbeKind {
return c.kinds
}
19 changes: 19 additions & 0 deletions fxhealthcheck/define_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fxhealthcheck_test

import (
"testing"

"github.com/ankorstore/yokai/fxhealthcheck"
"github.com/ankorstore/yokai/healthcheck"
"github.com/stretchr/testify/assert"
)

func TestNewCheckerProbeDefinition(t *testing.T) {
t.Parallel()

definition := fxhealthcheck.NewCheckerProbeDefinition("test", healthcheck.Liveness, healthcheck.Readiness)

assert.Implements(t, (*fxhealthcheck.CheckerProbeDefinition)(nil), definition)
assert.Equal(t, "test", definition.ReturnType())
assert.Equal(t, []healthcheck.ProbeKind{healthcheck.Liveness, healthcheck.Readiness}, definition.Kinds())
}
20 changes: 20 additions & 0 deletions fxhealthcheck/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module github.com/ankorstore/yokai/fxhealthcheck

go 1.20

require (
github.com/ankorstore/yokai/healthcheck v1.0.0
github.com/stretchr/testify v1.8.4
go.uber.org/fx v1.20.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/dig v1.17.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.23.0 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading