[#224] Refactor logger tag configuration
All checks were successful
/ DCO (pull_request) Successful in 26s
/ Builds (pull_request) Successful in 1m0s
/ Vulncheck (pull_request) Successful in 55s
/ OCI image (pull_request) Successful in 1m32s
/ Lint (pull_request) Successful in 2m0s
/ Tests (pull_request) Successful in 57s
/ Integration tests (pull_request) Successful in 5m52s

Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
This commit is contained in:
Pavel Pogodaev 2025-03-21 13:38:43 +03:00
parent f0b86c8ba7
commit ce12a389c9
7 changed files with 72 additions and 33 deletions

View file

@ -7,6 +7,7 @@ This document outlines major changes between releases.
### Added ### Added
- Add handling quota limit reached error (#187) - Add handling quota limit reached error (#187)
- Add slash clipping for FileName attribute (#174) - Add slash clipping for FileName attribute (#174)
- Add new format of tag names config
## [0.32.3] - 2025-02-05 ## [0.32.3] - 2025-02-05

View file

@ -114,7 +114,8 @@ type (
} }
tagsConfig struct { tagsConfig struct {
tagLogs sync.Map tagLogs sync.Map
defaultLvl zap.AtomicLevel
} }
logLevelConfig struct { logLevelConfig struct {
@ -139,35 +140,54 @@ func newTagsConfig(v *viper.Viper, ll zapcore.Level) *tagsConfig {
// panic here is analogue of the similar panic during common log level initialization. // panic here is analogue of the similar panic during common log level initialization.
panic(err.Error()) panic(err.Error())
} }
t.defaultLvl = zap.NewAtomicLevelAt(ll)
return &t return &t
} }
func newLogLevelConfig(lvl zap.AtomicLevel, tagsConfig *tagsConfig) *logLevelConfig { func newLogLevelConfig(lvl zap.AtomicLevel, tagsConfig *tagsConfig) *logLevelConfig {
return &logLevelConfig{ return &logLevelConfig{
logLevel: lvl, logLevel: minLogLevel(lvl, tagsConfig),
tagsConfig: tagsConfig, tagsConfig: tagsConfig,
} }
} }
func minLogLevel(lvl zap.AtomicLevel, config *tagsConfig) zap.AtomicLevel {
minLvl := lvl
config.tagLogs.Range(func(_, value any) bool {
v := value.(zapcore.Level)
if v < minLvl.Level() {
minLvl = zap.NewAtomicLevelAt(v)
}
return true
})
return minLvl
}
func (l *logLevelConfig) update(cfg *viper.Viper, log *zap.Logger) { func (l *logLevelConfig) update(cfg *viper.Viper, log *zap.Logger) {
if lvl, err := getLogLevel(cfg); err != nil { lvl, err := getLogLevel(cfg)
if err != nil {
log.Warn(logs.LogLevelWontBeUpdated, zap.Error(err), logs.TagField(logs.TagApp)) log.Warn(logs.LogLevelWontBeUpdated, zap.Error(err), logs.TagField(logs.TagApp))
} else {
l.logLevel.SetLevel(lvl)
} }
if err := l.tagsConfig.update(cfg, l.logLevel.Level()); err != nil { if err := l.tagsConfig.update(cfg, l.logLevel.Level()); err != nil {
log.Warn(logs.TagsLogConfigWontBeUpdated, zap.Error(err), logs.TagField(logs.TagApp)) log.Warn(logs.TagsLogConfigWontBeUpdated, zap.Error(err), logs.TagField(logs.TagApp))
} }
l.logLevel.SetLevel(minLogLevel(zap.NewAtomicLevelAt(lvl), l.tagsConfig).Level())
} }
func (t *tagsConfig) LevelEnabled(tag string, tgtLevel zapcore.Level) bool { func (t *tagsConfig) LevelEnabled(tag string, tgtLevel zapcore.Level) (bool, bool) {
lvl, ok := t.tagLogs.Load(tag) lvl, ok := t.tagLogs.Load(tag)
if !ok { if !ok {
return false return false, false
} }
return lvl.(zapcore.Level).Enabled(tgtLevel) return lvl.(zapcore.Level).Enabled(tgtLevel), true
}
func (t *tagsConfig) DefaultLevel() zap.AtomicLevel {
return t.defaultLvl
} }
func (t *tagsConfig) update(cfg *viper.Viper, ll zapcore.Level) error { func (t *tagsConfig) update(cfg *viper.Viper, ll zapcore.Level) error {
@ -194,6 +214,7 @@ func (t *tagsConfig) update(cfg *viper.Viper, ll zapcore.Level) error {
for k, v := range tags { for k, v := range tags {
t.tagLogs.Store(k, v) t.tagLogs.Store(k, v)
} }
t.defaultLvl = zap.NewAtomicLevelAt(ll)
return nil return nil
} }

View file

@ -40,7 +40,8 @@ type zapCoreTagFilterWrapper struct {
} }
type TagFilterSettings interface { type TagFilterSettings interface {
LevelEnabled(tag string, lvl zapcore.Level) bool LevelEnabled(tag string, lvl zapcore.Level) (bool, bool)
DefaultLevel() zap.AtomicLevel
} }
func (c *zapCoreTagFilterWrapper) Enabled(level zapcore.Level) bool { func (c *zapCoreTagFilterWrapper) Enabled(level zapcore.Level) bool {
@ -63,24 +64,36 @@ func (c *zapCoreTagFilterWrapper) Check(entry zapcore.Entry, checked *zapcore.Ch
} }
func (c *zapCoreTagFilterWrapper) Write(entry zapcore.Entry, fields []zapcore.Field) error { func (c *zapCoreTagFilterWrapper) Write(entry zapcore.Entry, fields []zapcore.Field) error {
if c.shouldSkip(entry, fields) || c.shouldSkip(entry, c.extra) { shouldSkip, tagFound := c.shouldSkip(entry, fields)
if tagFound {
if shouldSkip {
return nil
}
return c.core.Write(entry, fields)
}
shouldSkip, tagFound = c.shouldSkip(entry, c.extra)
if tagFound {
if shouldSkip {
return nil
}
return c.core.Write(entry, fields)
}
if !c.settings.DefaultLevel().Enabled(entry.Level) {
return nil return nil
} }
return c.core.Write(entry, fields) return c.core.Write(entry, fields)
} }
func (c *zapCoreTagFilterWrapper) shouldSkip(entry zapcore.Entry, fields []zap.Field) bool { func (c *zapCoreTagFilterWrapper) shouldSkip(entry zapcore.Entry, fields []zap.Field) (bool, bool) {
for _, field := range fields { for _, field := range fields {
if field.Key == logs.TagFieldName && field.Type == zapcore.StringType { if field.Key == logs.TagFieldName && field.Type == zapcore.StringType {
if !c.settings.LevelEnabled(field.String, entry.Level) { enabled, found := c.settings.LevelEnabled(field.String, entry.Level)
return true return !enabled, found
}
break
} }
} }
return false, false
return false
} }
func (c *zapCoreTagFilterWrapper) Sync() error { func (c *zapCoreTagFilterWrapper) Sync() error {

View file

@ -113,7 +113,7 @@ const (
cfgLoggerTags = "logger.tags" cfgLoggerTags = "logger.tags"
cfgLoggerTagsPrefixTmpl = cfgLoggerTags + ".%d." cfgLoggerTagsPrefixTmpl = cfgLoggerTags + ".%d."
cfgLoggerTagsNameTmpl = cfgLoggerTagsPrefixTmpl + "name" cfgLoggerTagsNameTmpl = cfgLoggerTagsPrefixTmpl + "names"
cfgLoggerTagsLevelTmpl = cfgLoggerTagsPrefixTmpl + "level" cfgLoggerTagsLevelTmpl = cfgLoggerTagsPrefixTmpl + "level"
// Wallet. // Wallet.
@ -516,8 +516,8 @@ func fetchLogTagsConfig(v *viper.Viper, defaultLvl zapcore.Level) (map[string]za
res := make(map[string]zapcore.Level) res := make(map[string]zapcore.Level)
for i := 0; ; i++ { for i := 0; ; i++ {
name := v.GetString(fmt.Sprintf(cfgLoggerTagsNameTmpl, i)) tagNames := v.GetString(fmt.Sprintf(cfgLoggerTagsNameTmpl, i))
if name == "" { if tagNames == "" {
break break
} }
@ -529,7 +529,12 @@ func fetchLogTagsConfig(v *viper.Viper, defaultLvl zapcore.Level) (map[string]za
} }
} }
res[name] = lvl for _, tagName := range strings.Split(tagNames, ",") {
tagName = strings.TrimSpace(tagName)
if len(tagName) != 0 {
res[tagName] = lvl
}
}
} }
if len(res) == 0 && !v.IsSet(cfgLoggerTags) { if len(res) == 0 && !v.IsSet(cfgLoggerTags) {

View file

@ -20,8 +20,9 @@ HTTP_GW_LOGGER_SAMPLING_ENABLED=false
HTTP_GW_LOGGER_SAMPLING_INITIAL=100 HTTP_GW_LOGGER_SAMPLING_INITIAL=100
HTTP_GW_LOGGER_SAMPLING_THEREAFTER=100 HTTP_GW_LOGGER_SAMPLING_THEREAFTER=100
HTTP_GW_LOGGER_SAMPLING_INTERVAL=1s HTTP_GW_LOGGER_SAMPLING_INTERVAL=1s
HTTP_GW_LOGGER_TAGS_0_NAME=app HTTP_GW_LOGGER_TAGS_0_NAMES=app,datapath
HTTP_GW_LOGGER_TAGS_1_NAME=datapath HTTP_GW_LOGGER_TAGS_0_LEVEL=level
HTTP_GW_LOGGER_TAGS_1_NAME=external_storage_tree
HTTP_GW_SERVER_0_ADDRESS=0.0.0.0:443 HTTP_GW_SERVER_0_ADDRESS=0.0.0.0:443
HTTP_GW_SERVER_0_TLS_ENABLED=false HTTP_GW_SERVER_0_TLS_ENABLED=false

View file

@ -30,8 +30,7 @@ logger:
thereafter: 100 thereafter: 100
interval: 1s interval: 1s
tags: tags:
- name: app - names: app,datapath
- name: datapath
level: debug level: debug
server: server:

View file

@ -176,10 +176,9 @@ logger:
thereafter: 100 thereafter: 100
interval: 1s interval: 1s
tags: tags:
- name: "app" - names: "app,datapath"
level: info level: info
- name: "datapath" - names: "external_storage_tree"
- name: "external_storage_tree"
``` ```
| Parameter | Type | SIGHUP reload | Default value | Description | | Parameter | Type | SIGHUP reload | Default value | Description |
@ -199,14 +198,14 @@ parameter. Available tags:
```yaml ```yaml
tags: tags:
- name: "app" - names: "app,datapath"
level: info level: info
``` ```
| Parameter | Type | SIGHUP reload | Default value | Description | | Parameter | Type | SIGHUP reload | Default value | Description |
|-----------------------|------------|---------------|---------------------------|-------------------------------------------------------------------------------------------------------| |-----------|------------|---------------|---------------------------|-------------------------------------------------------------------------------------------------------|
| `name` | `string` | yes | | Tag name. Possible values see below in `Tag values` section. | | `names` | `[]string` | yes | | Tag names separated by `,`. Possible values see below in `Tag values` section. |
| `level` | `string` | yes | Value from `logger.level` | Logging level for specific tag. Possible values: `debug`, `info`, `warn`, `dpanic`, `panic`, `fatal`. | | `level` | `string` | yes | Value from `logger.level` | Logging level for specific tag. Possible values: `debug`, `info`, `warn`, `dpanic`, `panic`, `fatal`. |
### Tag values ### Tag values