Config Component :

- Change reloading component method : try to reload all component and store errors, report list of errors but don't break the reloading process

Package Logger :
- Fix bug with entry logger filtering

Package Viper:
- reword message log before reloading config file (watchFS)
- add message log after reloading config file (watchFS)

Package Status :
- Fix DATA Race with status/info
- Add component key into log error message for health
- Add component key into function to use it into info (name)
- Reword health message : no OK/KO (still into status info), add error message reporting

Package httpserver :
- status info : apply update status component, use key in name
- status info : optimize code

Package Request :
- Fix error in url path operation
- Status info : optimize code
- Status info : apply update component, add endpoint hostname with name

Package Static :
- apply status component update

Other :
- Bump dependencies
This commit is contained in:
nabbar
2022-11-17 16:54:51 +01:00
parent eb8097fad8
commit 52f0d6fa04
13 changed files with 131 additions and 74 deletions

View File

@@ -269,7 +269,8 @@ func (c *componentList) ComponentIsStarted() bool {
func (c *componentList) reloadOne(isReload []string, key string, getCfg FuncComponentConfigGet) ([]string, liberr.Error) {
var (
err liberr.Error
err = ErrorComponentReload.Error(nil)
e liberr.Error
cpt Component
)
@@ -283,37 +284,48 @@ func (c *componentList) reloadOne(isReload []string, key string, getCfg FuncComp
if dep := cpt.Dependencies(); len(dep) > 0 {
for _, k := range dep {
if isReload, err = c.reloadOne(isReload, k, getCfg); err != nil {
return isReload, err
if isReload, e = c.reloadOne(isReload, k, getCfg); e != nil {
err.AddParentError(e)
}
}
}
if err = cpt.Reload(getCfg); err != nil {
return isReload, err
if e = cpt.Reload(getCfg); e != nil {
er := ErrorComponentReload.ErrorParent(fmt.Errorf("component: %s", key))
er.AddParentError(e)
err.AddParentError(er)
} else {
c.ComponentSet(key, cpt)
isReload = append(isReload, key)
}
return isReload, nil
if !err.HasParent() {
err = nil
}
return isReload, err
}
func (c *componentList) ComponentReload(getCfg FuncComponentConfigGet) liberr.Error {
var (
err liberr.Error
err = ErrorComponentReload.Error(nil)
e liberr.Error
key string
isReload = make([]string, 0)
)
for _, key = range c.ComponentKeys() {
if isReload, err = c.reloadOne(isReload, key, getCfg); err != nil {
return err
if isReload, e = c.reloadOne(isReload, key, getCfg); e != nil {
err.AddParent(e)
}
}
return nil
if !err.HasParent() {
err = nil
}
return err
}
func (c *componentList) ComponentStop() {

16
go.mod
View File

@@ -4,10 +4,10 @@ go 1.19
require (
github.com/aws/aws-sdk-go-v2 v1.17.1
github.com/aws/aws-sdk-go-v2/config v1.18.0
github.com/aws/aws-sdk-go-v2/credentials v1.13.0
github.com/aws/aws-sdk-go-v2/config v1.18.1
github.com/aws/aws-sdk-go-v2/credentials v1.13.1
github.com/aws/aws-sdk-go-v2/service/iam v1.18.23
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.3
github.com/bits-and-blooms/bitset v1.3.3
github.com/c-bata/go-prompt v0.2.6
github.com/fatih/color v1.13.0
@@ -63,6 +63,7 @@ require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/ClickHouse/ch-go v0.49.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.3.0 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
@@ -72,6 +73,7 @@ require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/aokoli/goutils v1.1.1 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 // indirect
@@ -85,7 +87,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.17.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.17.3 // indirect
github.com/aws/smithy-go v1.13.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect
@@ -163,13 +165,13 @@ require (
github.com/nats-io/nuid v1.0.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/paulmach/orb v0.7.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/term v1.2.0-beta.2 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rivo/uniseg v0.4.2 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
@@ -190,7 +192,7 @@ require (
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opentelemetry.io/otel v1.11.1 // indirect
go.opentelemetry.io/otel/trace v1.11.1 // indirect
golang.org/x/crypto v0.2.0 // indirect
golang.org/x/crypto v0.3.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.2.0 // indirect

View File

@@ -467,6 +467,7 @@ func (p pool) StatusHealth(bindAddress string) error {
func (p pool) StatusRoute(keyPrefix string, sts libsts.RouteStatus) {
p.MapRun(func(srv Server) {
bind := srv.GetBindable()
sts.ComponentNew(fmt.Sprintf("%s-%s", keyPrefix, bind), srv.StatusComponent())
name := fmt.Sprintf("%s-%s", keyPrefix, bind)
sts.ComponentNew(name, srv.StatusComponent(name))
})
}

View File

@@ -74,7 +74,7 @@ type Server interface {
StatusInfo() (name string, release string, hash string)
StatusHealth() error
StatusComponent() libsts.Component
StatusComponent(key string) libsts.Component
}
func NewServer(cfg *ServerConfig) Server {
@@ -238,7 +238,7 @@ func (s *server) StatusInfo() (name string, release string, hash string) {
vers = strings.TrimLeft(vers, "Go")
vers = strings.TrimLeft(vers, "GO")
return fmt.Sprintf("%s [%s]", s.GetName(), s.GetBindable()), vers, ""
return fmt.Sprintf("%s [%s]", s.GetName(), s.GetBindable()), runtime.Version()[2:], ""
}
func (s *server) StatusHealth() error {
@@ -253,7 +253,7 @@ func (s *server) StatusHealth() error {
}
}
func (s *server) StatusComponent() libsts.Component {
func (s *server) StatusComponent(key string) libsts.Component {
if cfg := s.GetConfig(); cfg == nil {
cnf := config.ConfigStatus{
Mandatory: true,
@@ -262,8 +262,8 @@ func (s *server) StatusComponent() libsts.Component {
CacheTimeoutInfo: 30 * time.Second,
CacheTimeoutHealth: 5 * time.Second,
}
return cnf.Component(s.StatusInfo, s.StatusHealth)
return cnf.Component(key, s.StatusInfo, s.StatusHealth)
} else {
return cfg.Status.Component(s.StatusInfo, s.StatusHealth)
return cfg.Status.Component(key, s.StatusInfo, s.StatusHealth)
}
}

View File

@@ -182,11 +182,11 @@ func (o *_HookFile) Fire(entry *logrus.Entry) error {
ent := entry.Dup()
ent.Level = entry.Level
if !o.isStack() {
if o.isStack() {
ent.Data = o.filterKey(ent.Data, FieldStack)
}
if !o.isTimeStamp() {
if o.isTimeStamp() {
ent.Data = o.filterKey(ent.Data, FieldTime)
}

View File

@@ -163,11 +163,11 @@ func (o *_HookSyslog) Fire(entry *logrus.Entry) error {
ent := entry.Dup()
ent.Level = entry.Level
if !o.isStack() {
if o.isStack() {
ent.Data = o.filterKey(ent.Data, FieldStack)
}
if !o.isTimeStamp() {
if o.isTimeStamp() {
ent.Data = o.filterKey(ent.Data, FieldTime)
}

View File

@@ -35,7 +35,6 @@ import (
"io"
"net/http"
"net/url"
"os"
"path"
"runtime"
"strings"
@@ -85,11 +84,11 @@ func (r *request) _StatusInfo() (name string, release string, build string) {
}
if release == "" {
release = strings.TrimLeft(runtime.Version(), "go")
release = strings.TrimLeft(release, "Go")
release = strings.TrimLeft(release, "GO")
release = runtime.Version()[2:]
}
name = fmt.Sprintf("[%s] %s", edp, name)
return name, release, build
}
@@ -448,9 +447,9 @@ func (r *request) AddPath(raw bool, pathPart ...string) {
var str string
if raw {
str = strings.Replace(r.u.RawPath, "/", string(os.PathSeparator), -1)
str = path.Clean(r.u.RawPath)
} else {
str = strings.Replace(r.u.Path, "/", string(os.PathSeparator), -1)
str = path.Clean(r.u.Path)
}
for i := range pathPart {

View File

@@ -669,7 +669,7 @@ func (s *staticHandler) _statusHealthPath(pathFile string) error {
return nil
}
func (s *staticHandler) _statusComponentPath(pathFile string, mandatory bool, message libsts.FctMessage, infoCacheTimeout, healthCacheTimeout time.Duration) libsts.Component {
func (s *staticHandler) _statusComponentPath(key string, pathFile string, mandatory bool, message libsts.FctMessage, infoCacheTimeout, healthCacheTimeout time.Duration) libsts.Component {
fctSts := func() (name string, release string, hash string) {
return s._statusInfoPath(pathFile)
}
@@ -678,13 +678,13 @@ func (s *staticHandler) _statusComponentPath(pathFile string, mandatory bool, me
return s._statusHealthPath(pathFile)
}
return libsts.NewComponent(mandatory, fctSts, fctHlt, message, infoCacheTimeout, healthCacheTimeout)
return libsts.NewComponent(key, mandatory, fctSts, fctHlt, message, infoCacheTimeout, healthCacheTimeout)
}
func (s *staticHandler) StatusComponent(mandatory bool, message libsts.FctMessage, infoCacheTimeout, healthCacheTimeout time.Duration, sts libsts.RouteStatus) {
for _, p := range s._getBase() {
name := fmt.Sprintf("%s-%s", strings.ReplaceAll(textEmbed, " ", "."), p)
sts.ComponentNew(name, s._statusComponentPath(p, mandatory, message, infoCacheTimeout, healthCacheTimeout))
sts.ComponentNew(name, s._statusComponentPath(name, p, mandatory, message, infoCacheTimeout, healthCacheTimeout))
}
}

View File

@@ -41,10 +41,10 @@ type Component interface {
Clean()
}
func NewComponent(mandatory bool, info FctInfo, health FctHealth, msg FctMessage, infoCacheDuration, statusCacheDuration time.Duration) Component {
func NewComponent(key string, mandatory bool, info FctInfo, health FctHealth, msg FctMessage, infoCacheDuration, statusCacheDuration time.Duration) Component {
return &cpt{
i: NewInfo(info, mandatory, infoCacheDuration),
s: NewStatus(health, msg, statusCacheDuration),
s: NewStatus(key, health, msg, statusCacheDuration),
}
}

View File

@@ -111,9 +111,9 @@ func (c *ConfigStatus) fctMessage() (msgOk string, msgKO string) {
}
func (c *ConfigStatus) RegisterStatus(sts libsts.RouteStatus, key string, fctInfo libsts.FctInfo, fctHealth libsts.FctHealth) {
sts.ComponentNew(key, status.NewComponent(c.Mandatory, fctInfo, fctHealth, c.fctMessage, c.CacheTimeoutInfo, c.CacheTimeoutHealth))
sts.ComponentNew(key, status.NewComponent(key, c.Mandatory, fctInfo, fctHealth, c.fctMessage, c.CacheTimeoutInfo, c.CacheTimeoutHealth))
}
func (c *ConfigStatus) Component(fctInfo libsts.FctInfo, fctHealth libsts.FctHealth) libsts.Component {
return status.NewComponent(c.Mandatory, fctInfo, fctHealth, c.fctMessage, c.CacheTimeoutInfo, c.CacheTimeoutHealth)
func (c *ConfigStatus) Component(key string, fctInfo libsts.FctInfo, fctHealth libsts.FctHealth) libsts.Component {
return status.NewComponent(key, c.Mandatory, fctInfo, fctHealth, c.fctMessage, c.CacheTimeoutInfo, c.CacheTimeoutHealth)
}

View File

@@ -26,11 +26,14 @@
package status
import (
"fmt"
"sync"
"time"
"github.com/gin-gonic/gin"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
"github.com/gin-gonic/gin"
)
type FctHealth func() error
@@ -54,11 +57,12 @@ type Status interface {
IsValid() bool
}
func NewStatus(health FctHealth, msg FctMessage, cacheDuration time.Duration) Status {
func NewStatus(key string, health FctHealth, msg FctMessage, cacheDuration time.Duration) Status {
return &status{
m: sync.Mutex{},
fh: health,
fm: msg,
k: key,
c: nil,
t: time.Time{},
d: cacheDuration,
@@ -70,6 +74,7 @@ type status struct {
fh FctHealth
fm FctMessage
k string
c *StatusResponse
t time.Time
d time.Duration
@@ -112,26 +117,34 @@ func (s *status) getCache() StatusResponse {
return s.c.Clone()
}
func (s *status) getKey() string {
s.m.Lock()
defer s.m.Unlock()
return s.k
}
func (s *status) Get(x *gin.Context) StatusResponse {
if !s.IsValid() {
var (
err error
msgOk string
msgKO string
)
var err error
msgOk, msgKO = s.getInfo()
err = s.getHealth()
c := &StatusResponse{}
if err != nil {
c.Status = DefMessageKO
c.Message = msgKO
liblog.ErrorLevel.LogErrorCtx(liblog.DebugLevel, "get health status", err)
if e, ok := err.(liberr.Error); ok {
c.Message = fmt.Sprintf("%v", e.GetError())
liblog.ErrorLevel.LogErrorCtxf(liblog.DebugLevel, "[%s] get health status", e.GetErrorFull(", "), s.getKey())
} else {
c.Message = fmt.Sprintf("%v", err)
liblog.ErrorLevel.LogErrorCtxf(liblog.DebugLevel, "[%s] get health status", err, s.getKey())
}
} else {
c.Status = DefMessageOK
c.Message = msgOk
c.Message = ""
}
s.setCache(c)

View File

@@ -26,6 +26,7 @@
package status
import (
"sync"
"time"
"github.com/gin-gonic/gin"
@@ -58,7 +59,7 @@ type Info interface {
func NewInfo(fct FctInfo, mandatory bool, cacheDuration time.Duration) Info {
return &info{
f: fct,
m: mandatory,
o: mandatory,
c: nil,
t: time.Time{},
d: cacheDuration,
@@ -66,8 +67,9 @@ func NewInfo(fct FctInfo, mandatory bool, cacheDuration time.Duration) Info {
}
type info struct {
m sync.Mutex
f FctInfo
m bool
o bool
c *InfoResponse
t time.Time
d time.Duration
@@ -75,34 +77,24 @@ type info struct {
func (i *info) Get(x *gin.Context) InfoResponse {
if !i.IsValid() {
var (
name string
vers string
hash string
)
if i.f != nil {
name, vers, hash = i.f()
i.regenCache()
}
i.c = &InfoResponse{
Name: name,
Release: vers,
HashBuild: hash,
Mandatory: i.m,
}
i.t = time.Now()
}
return i.c.Clone()
return i.clone()
}
func (i *info) Clean() {
i.m.Lock()
defer i.m.Unlock()
i.c = nil
i.t = time.Now()
}
func (i *info) IsValid() bool {
i.m.Lock()
defer i.m.Unlock()
if i.c == nil {
return false
} else if i.t.IsZero() {
@@ -112,3 +104,40 @@ func (i *info) IsValid() bool {
}
return true
}
func (i *info) regenCache() {
var (
name string
vers string
hash string
)
i.m.Lock()
defer i.m.Unlock()
if i.f != nil {
name, vers, hash = i.f()
}
i.c = &InfoResponse{
Name: name,
Release: vers,
HashBuild: hash,
Mandatory: i.o,
}
i.t = time.Now()
}
func (i *info) clone() InfoResponse {
i.m.Lock()
defer i.m.Unlock()
if i.c != nil {
return i.c.Clone()
}
return InfoResponse{
Mandatory: i.o,
}
}

View File

@@ -67,8 +67,9 @@ func (v *viper) WatchFS(logLevelFSInfo liblog.Level) {
v.v.WatchConfig()
v.v.OnConfigChange(func(e libnot.Event) {
if v.remote.fct != nil {
logLevelFSInfo.Logf("reloaded config file '%s'...", e.Name)
logLevelFSInfo.Logf("Reloading local config file '%s'...", e.Name)
v.remote.fct()
logLevelFSInfo.Logf("local config file '%s' has been reloaded.", e.Name)
}
})
}