summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/mattermost-server/v6/shared/mlog')
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/default.go63
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/global.go132
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/levels.go58
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/mlog.go419
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/options.go55
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/tlog.go79
6 files changed, 806 insertions, 0 deletions
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/default.go b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/default.go
new file mode 100644
index 00000000..0567c016
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/default.go
@@ -0,0 +1,63 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package mlog
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "os"
+)
+
+// defaultLog manually encodes the log to STDERR, providing a basic, default logging implementation
+// before mlog is fully configured.
+func defaultLog(level Level, msg string, fields ...Field) {
+ mFields := make(map[string]string)
+ buf := &bytes.Buffer{}
+
+ for _, fld := range fields {
+ buf.Reset()
+ fld.ValueString(buf, shouldQuote)
+ mFields[fld.Key] = buf.String()
+ }
+
+ log := struct {
+ Level string `json:"level"`
+ Message string `json:"msg"`
+ Fields map[string]string `json:"fields,omitempty"`
+ }{
+ level.Name,
+ msg,
+ mFields,
+ }
+
+ if b, err := json.Marshal(log); err != nil {
+ fmt.Fprintf(os.Stderr, `{"level":"error","msg":"failed to encode log message"}%s`, "\n")
+ } else {
+ fmt.Fprintf(os.Stderr, "%s\n", b)
+ }
+}
+
+func defaultIsLevelEnabled(level Level) bool {
+ return true
+}
+
+func defaultCustomMultiLog(lvl []Level, msg string, fields ...Field) {
+ for _, level := range lvl {
+ defaultLog(level, msg, fields...)
+ }
+}
+
+// shouldQuote returns true if val contains any characters that require quotations.
+func shouldQuote(val string) bool {
+ for _, c := range val {
+ if !((c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ c == '-' || c == '.' || c == '_' || c == '/' || c == '@' || c == '^' || c == '+') {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/global.go b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/global.go
new file mode 100644
index 00000000..de346123
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/global.go
@@ -0,0 +1,132 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package mlog
+
+import (
+ "sync"
+)
+
+var (
+ globalLogger *Logger
+ muxGlobalLogger sync.RWMutex
+)
+
+func InitGlobalLogger(logger *Logger) {
+ muxGlobalLogger.Lock()
+ defer muxGlobalLogger.Unlock()
+
+ globalLogger = logger
+}
+
+func getGlobalLogger() *Logger {
+ muxGlobalLogger.RLock()
+ defer muxGlobalLogger.RUnlock()
+
+ return globalLogger
+}
+
+// IsLevelEnabled returns true only if at least one log target is
+// configured to emit the specified log level. Use this check when
+// gathering the log info may be expensive.
+//
+// Note, transformations and serializations done via fields are already
+// lazily evaluated and don't require this check beforehand.
+func IsLevelEnabled(level Level) bool {
+ logger := getGlobalLogger()
+ if logger == nil {
+ return defaultIsLevelEnabled(level)
+ }
+ return logger.IsLevelEnabled(level)
+}
+
+// Log emits the log record for any targets configured for the specified level.
+func Log(level Level, msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(level, msg, fields...)
+ return
+ }
+ logger.Log(level, msg, fields...)
+}
+
+// LogM emits the log record for any targets configured for the specified levels.
+// Equivalent to calling `Log` once for each level.
+func LogM(levels []Level, msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultCustomMultiLog(levels, msg, fields...)
+ return
+ }
+ logger.LogM(levels, msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Trace` level.
+func Trace(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlTrace, msg, fields...)
+ return
+ }
+ logger.Trace(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Debug` level.
+func Debug(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlDebug, msg, fields...)
+ return
+ }
+ logger.Debug(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Info` level.
+func Info(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlInfo, msg, fields...)
+ return
+ }
+ logger.Info(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Warn` level.
+func Warn(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlWarn, msg, fields...)
+ return
+ }
+ logger.Warn(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Error` level.
+func Error(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlError, msg, fields...)
+ return
+ }
+ logger.Error(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Critical` level.
+// DEPRECATED: Either use Error or Fatal.
+func Critical(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlCritical, msg, fields...)
+ return
+ }
+ logger.Critical(msg, fields...)
+}
+
+func Fatal(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlFatal, msg, fields...)
+ return
+ }
+ logger.Fatal(msg, fields...)
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/levels.go b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/levels.go
new file mode 100644
index 00000000..c0b30996
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/levels.go
@@ -0,0 +1,58 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package mlog
+
+import "github.com/mattermost/logr/v2"
+
+// Standard levels.
+var (
+ LvlPanic = logr.Panic // ID = 0
+ LvlFatal = logr.Fatal // ID = 1
+ LvlError = logr.Error // ID = 2
+ LvlWarn = logr.Warn // ID = 3
+ LvlInfo = logr.Info // ID = 4
+ LvlDebug = logr.Debug // ID = 5
+ LvlTrace = logr.Trace // ID = 6
+ StdAll = []Level{LvlPanic, LvlFatal, LvlError, LvlWarn, LvlInfo, LvlDebug, LvlTrace}
+ // non-standard "critical" level
+ LvlCritical = Level{ID: 7, Name: "critical"}
+ // used by redirected standard logger
+ LvlStdLog = Level{ID: 10, Name: "stdlog"}
+ // used only by the logger
+ LvlLogError = Level{ID: 11, Name: "logerror", Stacktrace: true}
+)
+
+// Register custom (discrete) levels here.
+// !!!!! Custom ID's must be between 20 and 32,768 !!!!!!
+var (
+ // used by the audit system
+ LvlAuditAPI = Level{ID: 100, Name: "audit-api"}
+ LvlAuditContent = Level{ID: 101, Name: "audit-content"}
+ LvlAuditPerms = Level{ID: 102, Name: "audit-permissions"}
+ LvlAuditCLI = Level{ID: 103, Name: "audit-cli"}
+
+ // used by the TCP log target
+ LvlTCPLogTarget = Level{ID: 120, Name: "TcpLogTarget"}
+
+ // used by Remote Cluster Service
+ LvlRemoteClusterServiceDebug = Level{ID: 130, Name: "RemoteClusterServiceDebug"}
+ LvlRemoteClusterServiceError = Level{ID: 131, Name: "RemoteClusterServiceError"}
+ LvlRemoteClusterServiceWarn = Level{ID: 132, Name: "RemoteClusterServiceWarn"}
+
+ // used by Shared Channel Sync Service
+ LvlSharedChannelServiceDebug = Level{ID: 200, Name: "SharedChannelServiceDebug"}
+ LvlSharedChannelServiceError = Level{ID: 201, Name: "SharedChannelServiceError"}
+ LvlSharedChannelServiceWarn = Level{ID: 202, Name: "SharedChannelServiceWarn"}
+ LvlSharedChannelServiceMessagesInbound = Level{ID: 203, Name: "SharedChannelServiceMsgInbound"}
+ LvlSharedChannelServiceMessagesOutbound = Level{ID: 204, Name: "SharedChannelServiceMsgOutbound"}
+
+ // Focalboard
+ LvlFBTelemetry = Level{ID: 9000, Name: "telemetry"}
+ LvlFBMetrics = Level{ID: 9001, Name: "metrics"}
+)
+
+// Combinations for LogM (log multi).
+var (
+ MLvlAuditAll = []Level{LvlAuditAPI, LvlAuditContent, LvlAuditPerms, LvlAuditCLI}
+)
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/mlog.go b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/mlog.go
new file mode 100644
index 00000000..ac56362c
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/mlog.go
@@ -0,0 +1,419 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+// Package mlog provides a simple wrapper around Logr.
+package mlog
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "github.com/mattermost/logr/v2"
+ logrcfg "github.com/mattermost/logr/v2/config"
+)
+
+const (
+ ShutdownTimeout = time.Second * 15
+ FlushTimeout = time.Second * 15
+ DefaultMaxQueueSize = 1000
+ DefaultMetricsUpdateFreqMillis = 15000
+)
+
+type LoggerIFace interface {
+ IsLevelEnabled(Level) bool
+ Debug(string, ...Field)
+ Info(string, ...Field)
+ Warn(string, ...Field)
+ Error(string, ...Field)
+ Critical(string, ...Field)
+ Log(Level, string, ...Field)
+ LogM([]Level, string, ...Field)
+}
+
+// Type and function aliases from Logr to limit the spread of dependencies.
+type Field = logr.Field
+type Level = logr.Level
+type Option = logr.Option
+type Target = logr.Target
+type TargetInfo = logr.TargetInfo
+type LogRec = logr.LogRec
+type LogCloner = logr.LogCloner
+type MetricsCollector = logr.MetricsCollector
+type TargetCfg = logrcfg.TargetCfg
+type Sugar = logr.Sugar
+
+// LoggerConfiguration is a map of LogTarget configurations.
+type LoggerConfiguration map[string]TargetCfg
+
+func (lc LoggerConfiguration) Append(cfg LoggerConfiguration) {
+ for k, v := range cfg {
+ lc[k] = v
+ }
+}
+
+func (lc LoggerConfiguration) toTargetCfg() map[string]logrcfg.TargetCfg {
+ tcfg := make(map[string]logrcfg.TargetCfg)
+ for k, v := range lc {
+ tcfg[k] = v
+ }
+ return tcfg
+}
+
+// Any picks the best supported field type based on type of val.
+// For best performance when passing a struct (or struct pointer),
+// implement `logr.LogWriter` on the struct, otherwise reflection
+// will be used to generate a string representation.
+var Any = logr.Any
+
+// Int64 constructs a field containing a key and Int64 value.
+var Int64 = logr.Int64
+
+// Int32 constructs a field containing a key and Int32 value.
+var Int32 = logr.Int32
+
+// Int constructs a field containing a key and Int value.
+var Int = logr.Int
+
+// Uint64 constructs a field containing a key and Uint64 value.
+var Uint64 = logr.Uint64
+
+// Uint32 constructs a field containing a key and Uint32 value.
+var Uint32 = logr.Uint32
+
+// Uint constructs a field containing a key and Uint value.
+var Uint = logr.Uint
+
+// Float64 constructs a field containing a key and Float64 value.
+var Float64 = logr.Float64
+
+// Float32 constructs a field containing a key and Float32 value.
+var Float32 = logr.Float32
+
+// String constructs a field containing a key and String value.
+var String = logr.String
+
+// Stringer constructs a field containing a key and a fmt.Stringer value.
+// The fmt.Stringer's `String` method is called lazily.
+var Stringer = func(key string, s fmt.Stringer) logr.Field {
+ if s == nil {
+ return Field{Key: key, Type: logr.StringType, String: ""}
+ }
+ return Field{Key: key, Type: logr.StringType, String: s.String()}
+}
+
+// Err constructs a field containing a default key ("error") and error value.
+var Err = func(err error) logr.Field {
+ return NamedErr("error", err)
+}
+
+// NamedErr constructs a field containing a key and error value.
+var NamedErr = func(key string, err error) logr.Field {
+ if err == nil {
+ return Field{Key: key, Type: logr.StringType, String: ""}
+ }
+ return Field{Key: key, Type: logr.StringType, String: err.Error()}
+}
+
+// Bool constructs a field containing a key and bool value.
+var Bool = logr.Bool
+
+// Time constructs a field containing a key and time.Time value.
+var Time = logr.Time
+
+// Duration constructs a field containing a key and time.Duration value.
+var Duration = logr.Duration
+
+// Millis constructs a field containing a key and timestamp value.
+// The timestamp is expected to be milliseconds since Jan 1, 1970 UTC.
+var Millis = logr.Millis
+
+// Array constructs a field containing a key and array value.
+var Array = logr.Array
+
+// Map constructs a field containing a key and map value.
+var Map = logr.Map
+
+// Logger provides a thin wrapper around a Logr instance. This is a struct instead of an interface
+// so that there are no allocations on the heap each interface method invocation. Normally not
+// something to be concerned about, but logging calls for disabled levels should have as little CPU
+// and memory impact as possible. Most of these wrapper calls will be inlined as well.
+type Logger struct {
+ log *logr.Logger
+ lockConfig *int32
+}
+
+// NewLogger creates a new Logger instance which can be configured via `(*Logger).Configure`.
+// Some options with invalid values can cause an error to be returned, however `NewLogger()`
+// using just defaults never errors.
+func NewLogger(options ...Option) (*Logger, error) {
+ options = append(options, logr.StackFilter(logr.GetPackageName("NewLogger")))
+
+ lgr, err := logr.New(options...)
+ if err != nil {
+ return nil, err
+ }
+
+ log := lgr.NewLogger()
+ var lockConfig int32
+
+ return &Logger{
+ log: &log,
+ lockConfig: &lockConfig,
+ }, nil
+}
+
+// Configure provides a new configuration for this logger.
+// Zero or more sources of config can be provided:
+// cfgFile - path to file containing JSON
+// cfgEscaped - JSON string probably from ENV var
+//
+// For each case JSON containing log targets is provided. Target name collisions are resolved
+// using the following precedence:
+// cfgFile > cfgEscaped
+func (l *Logger) Configure(cfgFile string, cfgEscaped string) error {
+ if atomic.LoadInt32(l.lockConfig) != 0 {
+ return ErrConfigurationLock
+ }
+
+ cfgMap := make(LoggerConfiguration)
+
+ // Add config from file
+ if cfgFile != "" {
+ b, err := ioutil.ReadFile(cfgFile)
+ if err != nil {
+ return fmt.Errorf("error reading logger config file %s: %w", cfgFile, err)
+ }
+
+ var mapCfgFile LoggerConfiguration
+ if err := json.Unmarshal(b, &mapCfgFile); err != nil {
+ return fmt.Errorf("error decoding logger config file %s: %w", cfgFile, err)
+ }
+ cfgMap.Append(mapCfgFile)
+ }
+
+ // Add config from escaped json string
+ if cfgEscaped != "" {
+ var mapCfgEscaped LoggerConfiguration
+ if err := json.Unmarshal([]byte(cfgEscaped), &mapCfgEscaped); err != nil {
+ return fmt.Errorf("error decoding logger config as escaped json: %w", err)
+ }
+ cfgMap.Append(mapCfgEscaped)
+ }
+
+ if len(cfgMap) == 0 {
+ return nil
+ }
+
+ return logrcfg.ConfigureTargets(l.log.Logr(), cfgMap.toTargetCfg(), nil)
+}
+
+// ConfigureTargets provides a new configuration for this logger via a `LoggerConfig` map.
+// Typically `mlog.Configure` is used instead which accepts JSON formatted configuration.
+func (l *Logger) ConfigureTargets(cfg LoggerConfiguration) error {
+ if atomic.LoadInt32(l.lockConfig) != 0 {
+ return ErrConfigurationLock
+ }
+ return logrcfg.ConfigureTargets(l.log.Logr(), cfg.toTargetCfg(), nil)
+}
+
+// LockConfiguration disallows further configuration changes until `UnlockConfiguration`
+// is called. The previous locked stated is returned.
+func (l *Logger) LockConfiguration() bool {
+ old := atomic.SwapInt32(l.lockConfig, 1)
+ return old != 0
+}
+
+// UnlockConfiguration allows configuration changes. The previous locked stated is returned.
+func (l *Logger) UnlockConfiguration() bool {
+ old := atomic.SwapInt32(l.lockConfig, 0)
+ return old != 0
+}
+
+// IsConfigurationLocked returns the current state of the configuration lock.
+func (l *Logger) IsConfigurationLocked() bool {
+ return atomic.LoadInt32(l.lockConfig) != 0
+}
+
+// With creates a new Logger with the specified fields. This is a light-weight
+// operation and can be called on demand.
+func (l *Logger) With(fields ...Field) *Logger {
+ logWith := l.log.With(fields...)
+ return &Logger{
+ log: &logWith,
+ lockConfig: l.lockConfig,
+ }
+}
+
+// IsLevelEnabled returns true only if at least one log target is
+// configured to emit the specified log level. Use this check when
+// gathering the log info may be expensive.
+//
+// Note, transformations and serializations done via fields are already
+// lazily evaluated and don't require this check beforehand.
+func (l *Logger) IsLevelEnabled(level Level) bool {
+ return l.log.IsLevelEnabled(level)
+}
+
+// Log emits the log record for any targets configured for the specified level.
+func (l *Logger) Log(level Level, msg string, fields ...Field) {
+ l.log.Log(level, msg, fields...)
+}
+
+// LogM emits the log record for any targets configured for the specified levels.
+// Equivalent to calling `Log` once for each level.
+func (l *Logger) LogM(levels []Level, msg string, fields ...Field) {
+ l.log.LogM(levels, msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Trace` level.
+func (l *Logger) Trace(msg string, fields ...Field) {
+ l.log.Trace(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Debug` level.
+func (l *Logger) Debug(msg string, fields ...Field) {
+ l.log.Debug(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Info` level.
+func (l *Logger) Info(msg string, fields ...Field) {
+ l.log.Info(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Warn` level.
+func (l *Logger) Warn(msg string, fields ...Field) {
+ l.log.Warn(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Error` level.
+func (l *Logger) Error(msg string, fields ...Field) {
+ l.log.Error(msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Critical` level.
+func (l *Logger) Critical(msg string, fields ...Field) {
+ l.log.Log(LvlCritical, msg, fields...)
+}
+
+// Convenience method equivalent to calling `Log` with the `Fatal` level,
+// followed by `os.Exit(1)`.
+func (l *Logger) Fatal(msg string, fields ...Field) {
+ l.log.Log(logr.Fatal, msg, fields...)
+ _ = l.Shutdown()
+ os.Exit(1)
+}
+
+// HasTargets returns true if at least one log target has been added.
+func (l *Logger) HasTargets() bool {
+ return l.log.Logr().HasTargets()
+}
+
+// StdLogger creates a standard logger backed by this logger.
+// All log records are output with the specified level.
+func (l *Logger) StdLogger(level Level) *log.Logger {
+ return l.log.StdLogger(level)
+}
+
+// StdLogWriter returns a writer that can be hooked up to the output of a golang standard logger
+// anything written will be interpreted as log entries and passed to this logger.
+func (l *Logger) StdLogWriter() io.Writer {
+ return &logWriter{
+ logger: l,
+ }
+}
+
+// RedirectStdLog redirects output from the standard library's package-global logger
+// to this logger at the specified level and with zero or more Field's. Since this logger already
+// handles caller annotations, timestamps, etc., it automatically disables the standard
+// library's annotations and prefixing.
+// A function is returned that restores the original prefix and flags and resets the standard
+// library's output to os.Stdout.
+func (l *Logger) RedirectStdLog(level Level, fields ...Field) func() {
+ return l.log.Logr().RedirectStdLog(level, fields...)
+}
+
+// RemoveTargets safely removes one or more targets based on the filtering method.
+// `f` should return true to delete the target, false to keep it.
+// When removing a target, best effort is made to write any queued log records before
+// closing, with cxt determining how much time can be spent in total.
+// Note, keep the timeout short since this method blocks certain logging operations.
+func (l *Logger) RemoveTargets(ctx context.Context, f func(ti TargetInfo) bool) error {
+ return l.log.Logr().RemoveTargets(ctx, f)
+}
+
+// SetMetricsCollector sets (or resets) the metrics collector to be used for gathering
+// metrics for all targets. Only targets added after this call will use the collector.
+//
+// To ensure all targets use a collector, use the `SetMetricsCollector` option when
+// creating the Logger instead, or configure/reconfigure the Logger after calling this method.
+func (l *Logger) SetMetricsCollector(collector MetricsCollector, updateFrequencyMillis int64) {
+ l.log.Logr().SetMetricsCollector(collector, updateFrequencyMillis)
+}
+
+// Sugar creates a new `Logger` with a less structured API. Any fields are preserved.
+func (l *Logger) Sugar(fields ...Field) Sugar {
+ return l.log.Sugar(fields...)
+}
+
+// Flush forces all targets to write out any queued log records with a default timeout.
+func (l *Logger) Flush() error {
+ ctx, cancel := context.WithTimeout(context.Background(), FlushTimeout)
+ defer cancel()
+ return l.log.Logr().FlushWithTimeout(ctx)
+}
+
+// Flush forces all targets to write out any queued log records with the specfified timeout.
+func (l *Logger) FlushWithTimeout(ctx context.Context) error {
+ return l.log.Logr().FlushWithTimeout(ctx)
+}
+
+// Shutdown shuts down the logger after making best efforts to flush any
+// remaining records.
+func (l *Logger) Shutdown() error {
+ ctx, cancel := context.WithTimeout(context.Background(), ShutdownTimeout)
+ defer cancel()
+ return l.log.Logr().ShutdownWithTimeout(ctx)
+}
+
+// Shutdown shuts down the logger after making best efforts to flush any
+// remaining records.
+func (l *Logger) ShutdownWithTimeout(ctx context.Context) error {
+ return l.log.Logr().ShutdownWithTimeout(ctx)
+}
+
+// GetPackageName reduces a fully qualified function name to the package name
+// By sirupsen: https://github.com/sirupsen/logrus/blob/master/entry.go
+func GetPackageName(f string) string {
+ for {
+ lastPeriod := strings.LastIndex(f, ".")
+ lastSlash := strings.LastIndex(f, "/")
+ if lastPeriod > lastSlash {
+ f = f[:lastPeriod]
+ } else {
+ break
+ }
+ }
+ return f
+}
+
+type logWriter struct {
+ logger *Logger
+}
+
+func (lw *logWriter) Write(p []byte) (int, error) {
+ lw.logger.Info(string(p))
+ return len(p), nil
+}
+
+// ErrConfigurationLock is returned when one of a logger's configuration APIs is called
+// while the configuration is locked.
+var ErrConfigurationLock = errors.New("configuration is locked")
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/options.go b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/options.go
new file mode 100644
index 00000000..3a98b480
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/options.go
@@ -0,0 +1,55 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package mlog
+
+import "github.com/mattermost/logr/v2"
+
+// MaxQueueSize is the maximum number of log records that can be queued.
+// If exceeded, `OnQueueFull` is called which determines if the log
+// record will be dropped or block until add is successful.
+// Defaults to DefaultMaxQueueSize.
+func MaxQueueSize(size int) Option {
+ return logr.MaxQueueSize(size)
+}
+
+// OnLoggerError, when not nil, is called any time an internal
+// logging error occurs. For example, this can happen when a
+// target cannot connect to its data sink.
+func OnLoggerError(f func(error)) Option {
+ return logr.OnLoggerError(f)
+}
+
+// OnQueueFull, when not nil, is called on an attempt to add
+// a log record to a full Logr queue.
+// `MaxQueueSize` can be used to modify the maximum queue size.
+// This function should return quickly, with a bool indicating whether
+// the log record should be dropped (true) or block until the log record
+// is successfully added (false). If nil then blocking (false) is assumed.
+func OnQueueFull(f func(rec *LogRec, maxQueueSize int) bool) Option {
+ return logr.OnQueueFull(f)
+}
+
+// OnTargetQueueFull, when not nil, is called on an attempt to add
+// a log record to a full target queue provided the target supports reporting
+// this condition.
+// This function should return quickly, with a bool indicating whether
+// the log record should be dropped (true) or block until the log record
+// is successfully added (false). If nil then blocking (false) is assumed.
+func OnTargetQueueFull(f func(target Target, rec *LogRec, maxQueueSize int) bool) Option {
+ return logr.OnTargetQueueFull(f)
+}
+
+// SetMetricsCollector enables metrics collection by supplying a MetricsCollector.
+// The MetricsCollector provides counters and gauges that are updated by log targets.
+// `updateFreqMillis` determines how often polled metrics are updated. Defaults to 15000 (15 seconds)
+// and must be at least 250 so we don't peg the CPU.
+func SetMetricsCollector(collector MetricsCollector, updateFreqMillis int64) Option {
+ return logr.SetMetricsCollector(collector, updateFreqMillis)
+}
+
+// StackFilter provides a list of package names to exclude from the top of
+// stack traces. The Logr packages are automatically filtered.
+func StackFilter(pkg ...string) Option {
+ return logr.StackFilter(pkg...)
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/tlog.go b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/tlog.go
new file mode 100644
index 00000000..ef8f6016
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/shared/mlog/tlog.go
@@ -0,0 +1,79 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package mlog
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "sync"
+
+ "github.com/mattermost/logr/v2"
+ "github.com/mattermost/logr/v2/formatters"
+ "github.com/mattermost/logr/v2/targets"
+)
+
+// AddWriterTarget adds a simple io.Writer target to an existing Logger.
+// The `io.Writer` can be a buffer which is useful for testing.
+// When adding a buffer to collect logs make sure to use `mlog.Buffer` which is
+// a thread safe version of `bytes.Buffer`.
+func AddWriterTarget(logger *Logger, w io.Writer, useJSON bool, levels ...Level) error {
+ filter := logr.NewCustomFilter(levels...)
+
+ var formatter logr.Formatter
+ if useJSON {
+ formatter = &formatters.JSON{EnableCaller: true}
+ } else {
+ formatter = &formatters.Plain{EnableCaller: true}
+ }
+
+ target := targets.NewWriterTarget(w)
+ return logger.log.Logr().AddTarget(target, "_testWriter", filter, formatter, 1000)
+}
+
+// CreateConsoleTestLogger creates a logger for unit tests. Log records are output to `os.Stdout`.
+// Logs can also be mirrored to the optional `io.Writer`.
+func CreateConsoleTestLogger(useJSON bool, level Level) *Logger {
+ logger, _ := NewLogger()
+
+ filter := logr.StdFilter{
+ Lvl: level,
+ Stacktrace: LvlPanic,
+ }
+
+ var formatter logr.Formatter
+ if useJSON {
+ formatter = &formatters.JSON{EnableCaller: true}
+ } else {
+ formatter = &formatters.Plain{EnableCaller: true}
+ }
+
+ target := targets.NewWriterTarget(os.Stdout)
+ if err := logger.log.Logr().AddTarget(target, "_testcon", filter, formatter, 1000); err != nil {
+ panic(err)
+ }
+ return logger
+}
+
+// Buffer provides a thread-safe buffer useful for logging to memory in unit tests.
+type Buffer struct {
+ buf bytes.Buffer
+ mux sync.Mutex
+}
+
+func (b *Buffer) Read(p []byte) (n int, err error) {
+ b.mux.Lock()
+ defer b.mux.Unlock()
+ return b.buf.Read(p)
+}
+func (b *Buffer) Write(p []byte) (n int, err error) {
+ b.mux.Lock()
+ defer b.mux.Unlock()
+ return b.buf.Write(p)
+}
+func (b *Buffer) String() string {
+ b.mux.Lock()
+ defer b.mux.Unlock()
+ return b.buf.String()
+}