diff --git a/config/cptList.go b/config/cptList.go index cb767ed..d83e889 100644 --- a/config/cptList.go +++ b/config/cptList.go @@ -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() { diff --git a/go.mod b/go.mod index 7461d15..4daccb4 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/httpserver/pool.go b/httpserver/pool.go index ab0295c..3950456 100644 --- a/httpserver/pool.go +++ b/httpserver/pool.go @@ -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)) }) } diff --git a/httpserver/server.go b/httpserver/server.go index f6b06fd..63c605b 100644 --- a/httpserver/server.go +++ b/httpserver/server.go @@ -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) } } diff --git a/logger/hookfile.go b/logger/hookfile.go index 73aa9f8..3594669 100644 --- a/logger/hookfile.go +++ b/logger/hookfile.go @@ -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) } diff --git a/logger/hooksyslog.go b/logger/hooksyslog.go index fda93a0..fe07a91 100644 --- a/logger/hooksyslog.go +++ b/logger/hooksyslog.go @@ -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) } diff --git a/request/model.go b/request/model.go index df2f464..c4ca64e 100644 --- a/request/model.go +++ b/request/model.go @@ -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 { diff --git a/static/model.go b/static/model.go index 168e740..6fc8299 100644 --- a/static/model.go +++ b/static/model.go @@ -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)) } } diff --git a/status/component.go b/status/component.go index 24b974b..5c079cc 100644 --- a/status/component.go +++ b/status/component.go @@ -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), } } diff --git a/status/config/config.go b/status/config/config.go index ac26079..9b6de98 100644 --- a/status/config/config.go +++ b/status/config/config.go @@ -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) } diff --git a/status/health.go b/status/health.go index c55a1c4..e199c10 100644 --- a/status/health.go +++ b/status/health.go @@ -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) diff --git a/status/info.go b/status/info.go index bf77bd5..51e7360 100644 --- a/status/info.go +++ b/status/info.go @@ -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.c = &InfoResponse{ - Name: name, - Release: vers, - HashBuild: hash, - Mandatory: i.m, - } - i.t = time.Now() + i.regenCache() } - 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, + } +} diff --git a/viper/watch.go b/viper/watch.go index 6c00ef4..f7098b3 100644 --- a/viper/watch.go +++ b/viper/watch.go @@ -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) } }) }