[MM-54319] Add AdvancedLoggingJSON setting to system console (#24733)

* Add AdvancedLoggingJSON setting to system console

* Apply suggestions from code review

Co-authored-by: Doug Lauder <wiggin77@warpmail.net>

* Add validation for AdvancedLoggingJSON

---------

Co-authored-by: Doug Lauder <wiggin77@warpmail.net>
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Ben Schumacher
2023-10-25 16:40:07 +02:00
коммит произвёл GitHub
родитель 0844968d81
Коммит 671cf6cc3d
7 изменённых файлов: 194 добавлений и 1 удалений

Просмотреть файл

@@ -8730,6 +8730,14 @@
"id": "model.config.is_valid.localization.available_locales.app_error",
"translation": "Available Languages must contain Default Client Language."
},
{
"id": "model.config.is_valid.log.advanced_logging.json",
"translation": "Failed to parse JSON: {{.Error}}"
},
{
"id": "model.config.is_valid.log.advanced_logging.parse",
"translation": "Invalid format: {{.Error}}"
},
{
"id": "model.config.is_valid.login_attempts.app_error",
"translation": "Invalid maximum login attempts for service settings. Must be a positive number."

Просмотреть файл

@@ -1285,6 +1285,21 @@ func NewLogSettings() *LogSettings {
return settings
}
func (s *LogSettings) isValid() *AppError {
cfg := make(mlog.LoggerConfiguration)
err := json.Unmarshal(s.GetAdvancedLoggingConfig(), &cfg)
if err != nil {
return NewAppError("LogSettings.isValid", "model.config.is_valid.log.advanced_logging.json", map[string]any{"Error": err}, "", http.StatusBadRequest).Wrap(err)
}
err = cfg.IsValid()
if err != nil {
return NewAppError("LogSettings.isValid", "model.config.is_valid.log.advanced_logging.parse", map[string]any{"Error": err}, "", http.StatusBadRequest).Wrap(err)
}
return nil
}
func (s *LogSettings) SetDefaults() {
if s.EnableConsole == nil {
s.EnableConsole = NewBool(true)
@@ -3551,6 +3566,10 @@ func (o *Config) IsValid() *AppError {
return appErr
}
if appErr := o.LogSettings.isValid(); appErr != nil {
return appErr
}
if appErr := o.LocalizationSettings.isValid(); appErr != nil {
return appErr
}

Просмотреть файл

@@ -1208,6 +1208,109 @@ func TestLdapSettingsIsValid(t *testing.T) {
}
}
func TestLogSettingsIsValid(t *testing.T) {
for name, test := range map[string]struct {
LogSettings LogSettings
ExpectError bool
}{
"empty": {
LogSettings: LogSettings{},
ExpectError: false,
},
"AdvancedLoggingJSON contains empty string": {
LogSettings: LogSettings{
AdvancedLoggingJSON: json.RawMessage(``),
},
ExpectError: false,
},
"AdvancedLoggingJSON contains empty JSON": {
LogSettings: LogSettings{
AdvancedLoggingJSON: json.RawMessage(`{}`),
},
ExpectError: false,
},
"AdvancedLoggingJSON has JSON error ": {
LogSettings: LogSettings{
AdvancedLoggingJSON: json.RawMessage(`
{
"foo": "bar",
`),
},
ExpectError: true,
},
"AdvancedLoggingJSON has missing target": {
LogSettings: LogSettings{
AdvancedLoggingJSON: json.RawMessage(`
{
"foo": "bar",
}
`),
},
ExpectError: true,
},
"AdvancedLoggingJSON has an unknown Type": {
LogSettings: LogSettings{
AdvancedLoggingJSON: json.RawMessage(`
{
"console-log": {
"Type": "XYZ",
"Format": "json",
"Levels": [
{"ID": 10, "Name": "stdlog", "Stacktrace": false},
{"ID": 5, "Name": "debug", "Stacktrace": false},
{"ID": 4, "Name": "info", "Stacktrace": false, "color": 36},
{"ID": 3, "Name": "warn", "Stacktrace": false, "color": 33},
{"ID": 2, "Name": "error", "Stacktrace": true, "color": 31},
{"ID": 1, "Name": "fatal", "Stacktrace": true},
{"ID": 0, "Name": "panic", "Stacktrace": true}
],
"Options": {
"Out": "stdout"
},
"MaxQueueSize": 1000
}
}
`),
},
ExpectError: true,
},
"AdvancedLoggingJSON is valid": {
LogSettings: LogSettings{
AdvancedLoggingJSON: json.RawMessage(`
{
"console-log": {
"Type": "console",
"Format": "json",
"Levels": [
{"ID": 5, "Name": "debug", "Stacktrace": false},
{"ID": 4, "Name": "info", "Stacktrace": false, "color": 36},
{"ID": 3, "Name": "warn", "Stacktrace": false, "color": 33},
{"ID": 2, "Name": "error", "Stacktrace": true, "color": 31}
],
"Options": {
"Out": "stdout"
},
"MaxQueueSize": 1000
}
}
`),
},
ExpectError: false,
},
} {
t.Run(name, func(t *testing.T) {
test.LogSettings.SetDefaults()
appErr := test.LogSettings.isValid()
if test.ExpectError {
assert.NotNil(t, appErr)
} else {
assert.Nil(t, appErr)
}
})
}
}
func TestConfigSanitize(t *testing.T) {
c := Config{}
c.SetDefaults()

Просмотреть файл

@@ -7,7 +7,6 @@ package mlog
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
@@ -16,6 +15,8 @@ import (
"sync/atomic"
"time"
"github.com/pkg/errors"
"github.com/mattermost/logr/v2"
logrcfg "github.com/mattermost/logr/v2/config"
)
@@ -68,6 +69,21 @@ func (lc LoggerConfiguration) Append(cfg LoggerConfiguration) {
}
}
func (lc LoggerConfiguration) IsValid() error {
logger, err := logr.New()
if err != nil {
return errors.Wrap(err, "failed to create logger")
}
defer logger.Shutdown()
err = logrcfg.ConfigureTargets(logger, lc, nil)
if err != nil {
return errors.Wrap(err, "logger configuration is invalid")
}
return nil
}
func (lc LoggerConfiguration) toTargetCfg() map[string]logrcfg.TargetCfg {
tcfg := make(map[string]logrcfg.TargetCfg)
for k, v := range lc {