mirror of
https://github.com/nabbar/golib.git
synced 2025-12-24 11:51:02 +08:00
Refactor package errors + packages names :
- Refactor ErrorType, list errors managment, codeError - Add interface Error with error interface implement - Add type CodeError assign typiclly to const that represent code of error - Add func to registry func to retrieve message from an uint16 codeError (typicaly a switch of each codeError const) - Add default errorCode with default errorMessage if no one code or message is found - Add modeError to manage how to manage compatibility between Error interface and error interface - Add Error interface that allow parent link (parent as error or Error interface), code and trace management - Add trace finder to allow find func/file/line caller when Error is call - Add http 2 transport in httpcli - Add http 2 transport in httpserver - Add function to get client http with timeout management in httpcli - Add function to get Error if occurs of http client in httpcli - Add test for smtp package - Chg return error by returning Error in all packages - Chg package njs-archive by archive - Chg package njs-certif by certificates - Chg package njs-console by console - Chg package njs-crypt by crypt - Chg package njs-errors by errors - Chg package njs-httpcli by httpcli - Chg package njs-httpserver by httpserver - Chg package njs-ioutils by ioutils - Chg package njs-ldap by ldap - Chg package njs-logger by logger - Chg package njs-password by password - Chg package njs-progress by progress - Chg package njs-router by router - Chg package njs-semaphore by semaphore - Chg package njs-smtp by smtp - Chg package njs-static by static - Chg package njs-status by status - Chg package njs-version by version - Fix dependancies gopkg by github/go-ldap for go module compatibility - Fix gin Abort call by gin Abort with Error in static package - Fix issue #18 in status package : replace partner by component - Fix go vet error - Del deprecated function - Del useless function & files - Bump dependancies - Apply CHG in README.md
This commit is contained in:
0
status/README.md
Normal file
0
status/README.md
Normal file
324
status/status.go
Normal file
324
status/status.go
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
njs_router "github.com/nabbar/golib/router"
|
||||
|
||||
njs_version "github.com/nabbar/golib/version"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @TODO : see compliant with https://tools.ietf.org/html/draft-inadarei-api-health-check-02
|
||||
|
||||
type StatusItemResponse struct {
|
||||
Name string
|
||||
Status string
|
||||
Message string
|
||||
Release string
|
||||
HashBuild string
|
||||
}
|
||||
|
||||
type StatusResponse struct {
|
||||
StatusItemResponse
|
||||
Component []StatusItemResponse
|
||||
}
|
||||
|
||||
const statusOK = "OK"
|
||||
const statusKO = "KO"
|
||||
|
||||
type statusItem struct {
|
||||
name string
|
||||
build string
|
||||
msgOK string
|
||||
msgKO string
|
||||
health func() error
|
||||
release string
|
||||
}
|
||||
|
||||
type statusComponent struct {
|
||||
statusItem
|
||||
WarnIfErr bool
|
||||
later *initLater
|
||||
}
|
||||
|
||||
type mainPackage struct {
|
||||
statusItem
|
||||
cpt []statusComponent
|
||||
header gin.HandlerFunc
|
||||
later *initLater
|
||||
init bool
|
||||
}
|
||||
|
||||
type initLater struct {
|
||||
version func() njs_version.Version
|
||||
info func() (name, release, build string)
|
||||
msg func() (ok string, ko string)
|
||||
health func() error
|
||||
}
|
||||
|
||||
type Status interface {
|
||||
Register(prefix string, register njs_router.RegisterRouter)
|
||||
|
||||
AddComponent(name, msgOK, msgKO, release, build string, WarnIfError bool, health func() error)
|
||||
AddVersionComponent(vers njs_version.Version, msgOK, msgKO string, WarnIfError bool, health func() error)
|
||||
|
||||
LaterAddComponent(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, WarnIfError bool)
|
||||
LaterAddVersionComponent(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, WarnIfError bool)
|
||||
|
||||
Get(c *gin.Context)
|
||||
}
|
||||
|
||||
func NewStatusLater(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, Header gin.HandlerFunc) Status {
|
||||
return &mainPackage{
|
||||
cpt: make([]statusComponent, 0),
|
||||
header: Header,
|
||||
later: &initLater{
|
||||
version: nil,
|
||||
info: info,
|
||||
msg: msg,
|
||||
health: health,
|
||||
},
|
||||
init: false,
|
||||
}
|
||||
}
|
||||
|
||||
func NewStatus(name, msgOK, msgKO, release, build string, health func() error, Header gin.HandlerFunc) Status {
|
||||
return &mainPackage{
|
||||
statusItem: newItem(name, msgOK, msgKO, release, build, health),
|
||||
cpt: make([]statusComponent, 0),
|
||||
header: Header,
|
||||
later: nil,
|
||||
init: false,
|
||||
}
|
||||
}
|
||||
|
||||
func NewVersionStatusLater(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, Header gin.HandlerFunc) Status {
|
||||
return &mainPackage{
|
||||
cpt: make([]statusComponent, 0),
|
||||
header: Header,
|
||||
later: &initLater{
|
||||
version: vers,
|
||||
info: nil,
|
||||
msg: msg,
|
||||
health: health,
|
||||
},
|
||||
init: false,
|
||||
}
|
||||
}
|
||||
|
||||
func NewVersionStatus(vers njs_version.Version, msgOK, msgKO string, health func() error, Header gin.HandlerFunc) Status {
|
||||
return NewStatus(vers.GetPackage(), msgOK, msgKO, vers.GetRelease(), vers.GetBuild(), health, Header)
|
||||
}
|
||||
|
||||
func newItem(name, msgOK, msgKO, release, build string, health func() error) statusItem {
|
||||
return statusItem{
|
||||
name: name,
|
||||
build: build,
|
||||
msgOK: msgOK,
|
||||
msgKO: msgKO,
|
||||
health: health,
|
||||
release: release,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *mainPackage) AddComponent(name, msgOK, msgKO, release, build string, WarnIfError bool, health func() error) {
|
||||
p.cpt = append(p.cpt, statusComponent{
|
||||
statusItem: newItem(name, msgOK, msgKO, release, build, health),
|
||||
WarnIfErr: WarnIfError,
|
||||
later: nil,
|
||||
})
|
||||
}
|
||||
|
||||
func (p *mainPackage) LaterAddComponent(info func() (name, release, build string), msg func() (ok string, ko string), health func() error, WarnIfError bool) {
|
||||
p.cpt = append(p.cpt, statusComponent{
|
||||
WarnIfErr: WarnIfError,
|
||||
later: &initLater{
|
||||
version: nil,
|
||||
info: info,
|
||||
msg: msg,
|
||||
health: health,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *mainPackage) AddVersionComponent(vers njs_version.Version, msgOK, msgKO string, WarnIfError bool, health func() error) {
|
||||
p.AddComponent(vers.GetPackage(), msgOK, msgKO, vers.GetRelease(), vers.GetBuild(), WarnIfError, health)
|
||||
}
|
||||
|
||||
func (p *mainPackage) LaterAddVersionComponent(vers func() njs_version.Version, msg func() (ok string, ko string), health func() error, WarnIfError bool) {
|
||||
p.cpt = append(p.cpt, statusComponent{
|
||||
WarnIfErr: WarnIfError,
|
||||
later: &initLater{
|
||||
version: vers,
|
||||
info: nil,
|
||||
msg: msg,
|
||||
health: health,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *mainPackage) initStatus() {
|
||||
if p.later != nil {
|
||||
if p.later.info != nil {
|
||||
name, release, build := p.later.info()
|
||||
ok, ko := p.later.msg()
|
||||
p.statusItem = newItem(name, ok, ko, release, build, p.health)
|
||||
} else if p.later.version != nil {
|
||||
vers := p.later.version()
|
||||
ok, ko := p.later.msg()
|
||||
p.statusItem = newItem(vers.GetPackage(), ok, ko, vers.GetRelease(), vers.GetBuild(), p.health)
|
||||
}
|
||||
|
||||
if p.later.health != nil {
|
||||
p.health = p.later.health
|
||||
}
|
||||
|
||||
p.later = nil
|
||||
}
|
||||
|
||||
var cpt = make([]statusComponent, 0)
|
||||
|
||||
for _, part := range p.cpt {
|
||||
if part.later != nil {
|
||||
if part.later.info != nil {
|
||||
name, release, build := part.later.info()
|
||||
ok, ko := part.later.msg()
|
||||
part = statusComponent{
|
||||
statusItem: newItem(name, ok, ko, release, build, part.health),
|
||||
WarnIfErr: part.WarnIfErr,
|
||||
later: nil,
|
||||
}
|
||||
} else if p.later.version != nil {
|
||||
v := p.later.version()
|
||||
ok, ko := p.later.msg()
|
||||
part = statusComponent{
|
||||
statusItem: newItem(v.GetPackage(), ok, ko, v.GetRelease(), v.GetBuild(), part.health),
|
||||
WarnIfErr: part.WarnIfErr,
|
||||
later: nil,
|
||||
}
|
||||
}
|
||||
|
||||
if part.later.health != nil {
|
||||
part.health = part.later.health
|
||||
}
|
||||
}
|
||||
|
||||
cpt = append(cpt, part)
|
||||
}
|
||||
|
||||
p.init = true
|
||||
p.cpt = cpt
|
||||
}
|
||||
|
||||
func (p *mainPackage) cleanPrefix(prefix string) string {
|
||||
return path.Clean(strings.TrimRight(path.Join("/", prefix), "/"))
|
||||
}
|
||||
|
||||
func (p *mainPackage) Register(prefix string, register njs_router.RegisterRouter) {
|
||||
prefix = p.cleanPrefix(prefix)
|
||||
|
||||
register(http.MethodGet, prefix, p.header, p.Get)
|
||||
|
||||
if prefix != "/" {
|
||||
register(http.MethodGet, prefix+"/", p.header, p.Get)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *mainPackage) RegisterGroup(group, prefix string, register njs_router.RegisterRouterInGroup) {
|
||||
prefix = p.cleanPrefix(prefix)
|
||||
|
||||
register(group, http.MethodGet, prefix, p.header, p.Get)
|
||||
|
||||
if prefix != "/" {
|
||||
register(group, http.MethodGet, prefix+"/", p.header, p.Get)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *statusItem) GetStatusResponse(c *gin.Context) StatusItemResponse {
|
||||
res := StatusItemResponse{
|
||||
Name: p.name,
|
||||
Status: statusOK,
|
||||
Message: p.msgOK,
|
||||
Release: p.release,
|
||||
HashBuild: p.build,
|
||||
}
|
||||
|
||||
if p.health != nil {
|
||||
if err := p.health(); err != nil {
|
||||
msg := fmt.Sprintf("%s: %v", p.msgKO, err)
|
||||
c.Errors = append(c.Errors, &gin.Error{
|
||||
Err: fmt.Errorf(msg),
|
||||
Type: gin.ErrorTypePrivate,
|
||||
})
|
||||
res = StatusItemResponse{
|
||||
Name: p.name,
|
||||
Status: statusKO,
|
||||
Message: msg,
|
||||
Release: p.release,
|
||||
HashBuild: p.build,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (p *mainPackage) Get(c *gin.Context) {
|
||||
if !p.init {
|
||||
p.initStatus()
|
||||
}
|
||||
|
||||
hasError := false
|
||||
res := StatusResponse{
|
||||
p.GetStatusResponse(c),
|
||||
make([]StatusItemResponse, 0),
|
||||
}
|
||||
|
||||
for _, pkg := range p.cpt {
|
||||
pres := pkg.GetStatusResponse(c)
|
||||
if res.Status == statusOK && pres.Status == statusKO && !pkg.WarnIfErr {
|
||||
res.Status = statusKO
|
||||
} else if pres.Status == statusKO {
|
||||
hasError = true
|
||||
}
|
||||
res.Component = append(res.Component, pres)
|
||||
}
|
||||
|
||||
if res.Status != statusOK {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, &res)
|
||||
} else if hasError {
|
||||
c.JSON(http.StatusAccepted, &res)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, &res)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user