mirror of
https://github.com/mattermost/mattermost.git
synced 2026-02-03 20:40:00 -05:00
- Remove NotificationLogSettings configuration entirely - Add new notification-specific log levels (NotificationError, NotificationWarn, NotificationInfo, NotificationDebug, NotificationTrace) - Consolidate all notification logs into standard mattermost.log file - Update all notification logging code to use new multi-level logging (MlvlNotification*) - Remove notification logger infrastructure and support packet integration - Update test configurations and remove deprecated functionality tests - Add comprehensive tests for new notification log levels This change simplifies log analysis by unifying all application logging while maintaining flexibility through Advanced Logging configuration for administrators who need separate notification logs. 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude <noreply@anthropic.com>
214 lines
5.2 KiB
Go
214 lines
5.2 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
|
)
|
|
|
|
const (
|
|
LogRotateSizeMB = 100
|
|
LogCompress = true
|
|
LogRotateMaxAge = 0
|
|
LogRotateMaxBackups = 0
|
|
LogFilename = "mattermost.log"
|
|
LogMinLevelLen = 5
|
|
LogMinMsgLen = 45
|
|
LogDelim = " "
|
|
LogEnableCaller = true
|
|
)
|
|
|
|
type fileLocationFunc func(string) string
|
|
|
|
func MloggerConfigFromLoggerConfig(s *model.LogSettings, configSrc LogConfigSrc, getFileFunc fileLocationFunc) (mlog.LoggerConfiguration, error) {
|
|
cfg := make(mlog.LoggerConfiguration)
|
|
|
|
var targetCfg mlog.TargetCfg
|
|
var err error
|
|
|
|
// add the simple logging config
|
|
if *s.EnableConsole {
|
|
targetCfg, err = makeSimpleConsoleTarget(*s.ConsoleLevel, *s.ConsoleJson, *s.EnableColor)
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
cfg["_defConsole"] = targetCfg
|
|
}
|
|
|
|
if *s.EnableFile {
|
|
targetCfg, err = makeSimpleFileTarget(getFileFunc(*s.FileLocation), *s.FileLevel, *s.FileJson)
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
cfg["_defFile"] = targetCfg
|
|
}
|
|
|
|
if configSrc == nil {
|
|
return cfg, nil
|
|
}
|
|
|
|
// add advanced logging config
|
|
cfgAdv := configSrc.Get()
|
|
cfg.Append(cfgAdv)
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func MloggerConfigFromAuditConfig(auditSettings model.ExperimentalAuditSettings, configSrc LogConfigSrc) (mlog.LoggerConfiguration, error) {
|
|
cfg := make(mlog.LoggerConfiguration)
|
|
|
|
var targetCfg mlog.TargetCfg
|
|
var err error
|
|
|
|
// add the simple audit config
|
|
if *auditSettings.FileEnabled {
|
|
targetCfg, err = makeSimpleFileTarget(*auditSettings.FileName, "error", true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// apply audit specific levels
|
|
targetCfg.Levels = []mlog.Level{mlog.LvlAuditAPI, mlog.LvlAuditContent, mlog.LvlAuditPerms, mlog.LvlAuditCLI}
|
|
|
|
// apply audit specific formatting
|
|
targetCfg.FormatOptions = json.RawMessage(`{"disable_timestamp": false, "disable_msg": true, "disable_stacktrace": true, "disable_level": true}`)
|
|
|
|
cfg["_defAudit"] = targetCfg
|
|
}
|
|
|
|
if configSrc == nil {
|
|
return cfg, nil
|
|
}
|
|
|
|
// add advanced audit config
|
|
cfgAdv := configSrc.Get()
|
|
cfg.Append(cfgAdv)
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func GetLogFileLocation(fileLocation string) string {
|
|
if fileLocation == "" {
|
|
fileLocation, _ = fileutils.FindDir("logs")
|
|
}
|
|
|
|
return filepath.Join(fileLocation, LogFilename)
|
|
}
|
|
|
|
func makeSimpleConsoleTarget(level string, outputJSON bool, color bool) (mlog.TargetCfg, error) {
|
|
levels, err := stdLevels(level)
|
|
if err != nil {
|
|
return mlog.TargetCfg{}, err
|
|
}
|
|
|
|
target := mlog.TargetCfg{
|
|
Type: "console",
|
|
Levels: levels,
|
|
Options: json.RawMessage(`{"out": "stdout"}`),
|
|
MaxQueueSize: 1000,
|
|
}
|
|
|
|
if outputJSON {
|
|
target.Format = "json"
|
|
target.FormatOptions = makeJSONFormatOptions()
|
|
} else {
|
|
target.Format = "plain"
|
|
target.FormatOptions = makePlainFormatOptions(color)
|
|
}
|
|
return target, nil
|
|
}
|
|
|
|
func makeSimpleFileTarget(filename string, level string, json bool) (mlog.TargetCfg, error) {
|
|
levels, err := stdLevels(level)
|
|
if err != nil {
|
|
return mlog.TargetCfg{}, err
|
|
}
|
|
|
|
fileOpts, err := makeFileOptions(filename)
|
|
if err != nil {
|
|
return mlog.TargetCfg{}, fmt.Errorf("cannot encode file options: %w", err)
|
|
}
|
|
|
|
target := mlog.TargetCfg{
|
|
Type: "file",
|
|
Levels: levels,
|
|
Options: fileOpts,
|
|
MaxQueueSize: 1000,
|
|
}
|
|
|
|
if json {
|
|
target.Format = "json"
|
|
target.FormatOptions = makeJSONFormatOptions()
|
|
} else {
|
|
target.Format = "plain"
|
|
target.FormatOptions = makePlainFormatOptions(false)
|
|
}
|
|
return target, nil
|
|
}
|
|
|
|
func stdLevels(level string) ([]mlog.Level, error) {
|
|
stdLevel, err := stringToStdLevel(level)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var levels []mlog.Level
|
|
for _, l := range mlog.StdAll {
|
|
if l.ID <= stdLevel.ID {
|
|
levels = append(levels, l)
|
|
}
|
|
}
|
|
return levels, nil
|
|
}
|
|
|
|
func stringToStdLevel(level string) (mlog.Level, error) {
|
|
level = strings.ToLower(level)
|
|
for _, l := range mlog.StdAll {
|
|
if l.Name == level {
|
|
return l, nil
|
|
}
|
|
}
|
|
return mlog.Level{}, fmt.Errorf("%s is not a standard level", level)
|
|
}
|
|
|
|
func makeJSONFormatOptions() json.RawMessage {
|
|
str := fmt.Sprintf(`{"enable_caller": %t}`, LogEnableCaller)
|
|
return json.RawMessage(str)
|
|
}
|
|
|
|
func makePlainFormatOptions(enableColor bool) json.RawMessage {
|
|
str := fmt.Sprintf(`{"delim": "%s", "min_level_len": %d, "min_msg_len": %d, "enable_color": %t, "enable_caller": %t}`,
|
|
LogDelim, LogMinLevelLen, LogMinMsgLen, enableColor, LogEnableCaller)
|
|
return json.RawMessage(str)
|
|
}
|
|
|
|
func makeFileOptions(filename string) (json.RawMessage, error) {
|
|
opts := struct {
|
|
Filename string `json:"filename"`
|
|
Max_size int `json:"max_size"`
|
|
Max_age int `json:"max_age"`
|
|
Max_backups int `json:"max_backups"`
|
|
Compress bool `json:"compress"`
|
|
}{
|
|
Filename: filename,
|
|
Max_size: LogRotateSizeMB,
|
|
Max_age: LogRotateMaxAge,
|
|
Max_backups: LogRotateMaxBackups,
|
|
Compress: LogCompress,
|
|
}
|
|
|
|
b, err := json.Marshal(opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return json.RawMessage(b), nil
|
|
}
|