[#224] Refactor logger tag configuration
All checks were successful
/ DCO (pull_request) Successful in 28s
/ Vulncheck (pull_request) Successful in 52s
/ Builds (pull_request) Successful in 1m0s
/ OCI image (pull_request) Successful in 1m27s
/ Lint (pull_request) Successful in 1m53s
/ Tests (pull_request) Successful in 49s
/ Integration tests (pull_request) Successful in 5m30s
All checks were successful
/ DCO (pull_request) Successful in 28s
/ Vulncheck (pull_request) Successful in 52s
/ Builds (pull_request) Successful in 1m0s
/ OCI image (pull_request) Successful in 1m27s
/ Lint (pull_request) Successful in 1m53s
/ Tests (pull_request) Successful in 49s
/ Integration tests (pull_request) Successful in 5m30s
Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
This commit is contained in:
parent
0f73da258b
commit
901bf4171d
6 changed files with 65 additions and 36 deletions
|
@ -119,10 +119,15 @@ type (
|
||||||
|
|
||||||
logLevelConfig struct {
|
logLevelConfig struct {
|
||||||
logLevel zap.AtomicLevel
|
logLevel zap.AtomicLevel
|
||||||
|
maxLevel zap.AtomicLevel
|
||||||
tagsConfig *tagsConfig
|
tagsConfig *tagsConfig
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (l *logLevelConfig) MaxLevel() zap.AtomicLevel {
|
||||||
|
return l.maxLevel
|
||||||
|
}
|
||||||
|
|
||||||
func newLogLevel(v *viper.Viper) zap.AtomicLevel {
|
func newLogLevel(v *viper.Viper) zap.AtomicLevel {
|
||||||
ll, err := getLogLevel(v)
|
ll, err := getLogLevel(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -143,12 +148,27 @@ func newTagsConfig(v *viper.Viper, ll zapcore.Level) *tagsConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLogLevelConfig(lvl zap.AtomicLevel, tagsConfig *tagsConfig) *logLevelConfig {
|
func newLogLevelConfig(lvl zap.AtomicLevel, tagsConfig *tagsConfig) *logLevelConfig {
|
||||||
|
maxLvl := maxLogLevel(lvl, tagsConfig)
|
||||||
return &logLevelConfig{
|
return &logLevelConfig{
|
||||||
logLevel: lvl,
|
logLevel: maxLvl,
|
||||||
tagsConfig: tagsConfig,
|
tagsConfig: tagsConfig,
|
||||||
|
maxLevel: maxLvl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func maxLogLevel(lvl zap.AtomicLevel, config *tagsConfig) zap.AtomicLevel {
|
||||||
|
maxLvl := lvl
|
||||||
|
config.tagLogs.Range(func(_, value any) bool {
|
||||||
|
v := value.(zapcore.Level)
|
||||||
|
if v > maxLvl.Level() {
|
||||||
|
maxLvl = zap.NewAtomicLevelAt(v)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return maxLvl
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
if lvl, err := getLogLevel(cfg); err != nil {
|
||||||
log.Warn(logs.LogLevelWontBeUpdated, zap.Error(err), logs.TagField(logs.TagApp))
|
log.Warn(logs.LogLevelWontBeUpdated, zap.Error(err), logs.TagField(logs.TagApp))
|
||||||
|
@ -159,6 +179,8 @@ func (l *logLevelConfig) update(cfg *viper.Viper, log *zap.Logger) {
|
||||||
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.maxLevel = maxLogLevel(l.logLevel, l.tagsConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tagsConfig) LevelEnabled(tag string, tgtLevel zapcore.Level) bool {
|
func (t *tagsConfig) LevelEnabled(tag string, tgtLevel zapcore.Level) bool {
|
||||||
|
@ -203,7 +225,7 @@ func newApp(ctx context.Context, cfg *appCfg) App {
|
||||||
logLevel := newLogLevel(cfg.config())
|
logLevel := newLogLevel(cfg.config())
|
||||||
tagConfig := newTagsConfig(cfg.config(), logLevel.Level())
|
tagConfig := newTagsConfig(cfg.config(), logLevel.Level())
|
||||||
logConfig := newLogLevelConfig(logLevel, tagConfig)
|
logConfig := newLogLevelConfig(logLevel, tagConfig)
|
||||||
log := pickLogger(cfg.config(), logConfig.logLevel, logSettings, tagConfig)
|
log := pickLogger(cfg.config(), *logConfig, logSettings, tagConfig)
|
||||||
|
|
||||||
a := &app{
|
a := &app{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
|
|
@ -36,6 +36,7 @@ var _ zapcore.Core = (*zapCoreTagFilterWrapper)(nil)
|
||||||
type zapCoreTagFilterWrapper struct {
|
type zapCoreTagFilterWrapper struct {
|
||||||
core zapcore.Core
|
core zapcore.Core
|
||||||
settings TagFilterSettings
|
settings TagFilterSettings
|
||||||
|
maxLvl MaxLevelSetting
|
||||||
extra []zap.Field
|
extra []zap.Field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +44,10 @@ type TagFilterSettings interface {
|
||||||
LevelEnabled(tag string, lvl zapcore.Level) bool
|
LevelEnabled(tag string, lvl zapcore.Level) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MaxLevelSetting interface {
|
||||||
|
MaxLevel() zap.AtomicLevel
|
||||||
|
}
|
||||||
|
|
||||||
func (c *zapCoreTagFilterWrapper) Enabled(level zapcore.Level) bool {
|
func (c *zapCoreTagFilterWrapper) Enabled(level zapcore.Level) bool {
|
||||||
return c.core.Enabled(level)
|
return c.core.Enabled(level)
|
||||||
}
|
}
|
||||||
|
@ -51,6 +56,7 @@ func (c *zapCoreTagFilterWrapper) With(fields []zapcore.Field) zapcore.Core {
|
||||||
return &zapCoreTagFilterWrapper{
|
return &zapCoreTagFilterWrapper{
|
||||||
core: c.core.With(fields),
|
core: c.core.With(fields),
|
||||||
settings: c.settings,
|
settings: c.settings,
|
||||||
|
maxLvl: c.maxLvl,
|
||||||
extra: append(c.extra, fields...),
|
extra: append(c.extra, fields...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,24 +79,21 @@ func (c *zapCoreTagFilterWrapper) Write(entry zapcore.Entry, fields []zapcore.Fi
|
||||||
func (c *zapCoreTagFilterWrapper) shouldSkip(entry zapcore.Entry, fields []zap.Field) bool {
|
func (c *zapCoreTagFilterWrapper) shouldSkip(entry zapcore.Entry, fields []zap.Field) 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) {
|
return !c.settings.LevelEnabled(field.String, entry.Level)
|
||||||
return true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return !c.maxLvl.MaxLevel().Enabled(entry.Level)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zapCoreTagFilterWrapper) Sync() error {
|
func (c *zapCoreTagFilterWrapper) Sync() error {
|
||||||
return c.core.Sync()
|
return c.core.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyZapCoreMiddlewares(core zapcore.Core, v *viper.Viper, loggerSettings LoggerAppSettings, tagSetting TagFilterSettings) zapcore.Core {
|
func applyZapCoreMiddlewares(core zapcore.Core, v *viper.Viper, lvlCfg logLevelConfig, loggerSettings LoggerAppSettings, tagSetting TagFilterSettings) zapcore.Core {
|
||||||
core = &zapCoreTagFilterWrapper{
|
core = &zapCoreTagFilterWrapper{
|
||||||
core: core,
|
core: core,
|
||||||
settings: tagSetting,
|
settings: tagSetting,
|
||||||
|
maxLvl: &lvlCfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.GetBool(cfgLoggerSamplingEnabled) {
|
if v.GetBool(cfgLoggerSamplingEnabled) {
|
||||||
|
@ -126,33 +129,33 @@ func newLogEncoder() zapcore.Encoder {
|
||||||
// Logger records a stack trace for all messages at or above fatal level.
|
// Logger records a stack trace for all messages at or above fatal level.
|
||||||
//
|
//
|
||||||
// See also zapcore.Level, zap.NewProductionConfig, zap.AddStacktrace.
|
// See also zapcore.Level, zap.NewProductionConfig, zap.AddStacktrace.
|
||||||
func newStdoutLogger(v *viper.Viper, lvl zap.AtomicLevel, loggerSettings LoggerAppSettings, tagSetting TagFilterSettings) *Logger {
|
func newStdoutLogger(v *viper.Viper, lvlCfg logLevelConfig, loggerSettings LoggerAppSettings, tagSetting TagFilterSettings) *Logger {
|
||||||
stdout := zapcore.AddSync(os.Stderr)
|
stdout := zapcore.AddSync(os.Stderr)
|
||||||
|
|
||||||
consoleOutCore := zapcore.NewCore(newLogEncoder(), stdout, lvl)
|
consoleOutCore := zapcore.NewCore(newLogEncoder(), stdout, lvlCfg.logLevel)
|
||||||
consoleOutCore = applyZapCoreMiddlewares(consoleOutCore, v, loggerSettings, tagSetting)
|
consoleOutCore = applyZapCoreMiddlewares(consoleOutCore, v, lvlCfg, loggerSettings, tagSetting)
|
||||||
|
|
||||||
return &Logger{
|
return &Logger{
|
||||||
logger: zap.New(consoleOutCore, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))),
|
logger: zap.New(consoleOutCore, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))),
|
||||||
lvl: lvl,
|
lvl: lvlCfg.logLevel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newJournaldLogger(v *viper.Viper, lvl zap.AtomicLevel, loggerSettings LoggerAppSettings, tagSetting TagFilterSettings) *Logger {
|
func newJournaldLogger(v *viper.Viper, lvlCfg logLevelConfig, loggerSettings LoggerAppSettings, tagSetting TagFilterSettings) *Logger {
|
||||||
encoder := zapjournald.NewPartialEncoder(newLogEncoder(), zapjournald.SyslogFields)
|
encoder := zapjournald.NewPartialEncoder(newLogEncoder(), zapjournald.SyslogFields)
|
||||||
|
|
||||||
core := zapjournald.NewCore(lvl, encoder, &journald.Journal{}, zapjournald.SyslogFields)
|
core := zapjournald.NewCore(lvlCfg.logLevel, encoder, &journald.Journal{}, zapjournald.SyslogFields)
|
||||||
coreWithContext := core.With([]zapcore.Field{
|
coreWithContext := core.With([]zapcore.Field{
|
||||||
zapjournald.SyslogFacility(zapjournald.LogDaemon),
|
zapjournald.SyslogFacility(zapjournald.LogDaemon),
|
||||||
zapjournald.SyslogIdentifier(),
|
zapjournald.SyslogIdentifier(),
|
||||||
zapjournald.SyslogPid(),
|
zapjournald.SyslogPid(),
|
||||||
})
|
})
|
||||||
|
|
||||||
coreWithContext = applyZapCoreMiddlewares(coreWithContext, v, loggerSettings, tagSetting)
|
coreWithContext = applyZapCoreMiddlewares(coreWithContext, v, lvlCfg, loggerSettings, tagSetting)
|
||||||
|
|
||||||
return &Logger{
|
return &Logger{
|
||||||
logger: zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))),
|
logger: zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))),
|
||||||
lvl: lvl,
|
lvl: lvlCfg.logLevel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,14 +163,14 @@ type LoggerAppSettings interface {
|
||||||
DroppedLogsInc()
|
DroppedLogsInc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickLogger(v *viper.Viper, lvl zap.AtomicLevel, loggerSettings LoggerAppSettings, tagSettings TagFilterSettings) *Logger {
|
func pickLogger(v *viper.Viper, lvlCfg logLevelConfig, loggerSettings LoggerAppSettings, tagSettings TagFilterSettings) *Logger {
|
||||||
dest := v.GetString(cfgLoggerDestination)
|
dest := v.GetString(cfgLoggerDestination)
|
||||||
|
|
||||||
switch dest {
|
switch dest {
|
||||||
case destinationStdout:
|
case destinationStdout:
|
||||||
return newStdoutLogger(v, lvl, loggerSettings, tagSettings)
|
return newStdoutLogger(v, lvlCfg, loggerSettings, tagSettings)
|
||||||
case destinationJournald:
|
case destinationJournald:
|
||||||
return newJournaldLogger(v, lvl, loggerSettings, tagSettings)
|
return newJournaldLogger(v, lvlCfg, loggerSettings, tagSettings)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("wrong destination for logger: %s", dest))
|
panic(fmt.Sprintf("wrong destination for logger: %s", dest))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue