diff --git a/Makefile b/Makefile
index 8a432a676c..48ec022c94 100644
--- a/Makefile
+++ b/Makefile
@@ -453,8 +453,7 @@ run-server: prepackaged-binaries validate-go-version start-docker ## Starts the
@echo Running mattermost for development
mkdir -p $(BUILD_WEBAPP_DIR)/dist/files
- $(GO) run $(GOFLAGS) -ldflags '$(LDFLAGS)' $(PLATFORM_FILES) 2>&1 | \
- $(GO) run $(GOFLAGS) -ldflags '$(LDFLAGS)' $(PLATFORM_FILES) logs --logrus $(RUN_IN_BACKGROUND)
+ $(GO) run $(GOFLAGS) -ldflags '$(LDFLAGS)' $(PLATFORM_FILES) $(RUN_IN_BACKGROUND)
debug-server: start-docker ## Compile and start server using delve.
mkdir -p $(BUILD_WEBAPP_DIR)/dist/files
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index 9d259b7365..ce765a4ed3 100644
--- a/api4/apitestlib.go
+++ b/api4/apitestlib.go
@@ -33,7 +33,6 @@ import (
"github.com/mattermost/mattermost-server/v6/store/localcachelayer"
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
"github.com/mattermost/mattermost-server/v6/testlib"
- "github.com/mattermost/mattermost-server/v6/utils"
"github.com/mattermost/mattermost-server/v6/web"
"github.com/mattermost/mattermost-server/v6/wsapi"
)
@@ -67,6 +66,8 @@ type TestHelper struct {
LocalClient *model.Client4
IncludeCacheLayer bool
+
+ TestLogger *mlog.Logger
}
var mainHelper *testlib.MainHelper
@@ -120,6 +121,15 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
options = append(options, app.StoreOverride(dbStore))
}
+ testLogger, _ := mlog.NewLogger()
+ logCfg, _ := config.MloggerConfigFromLoggerConfig(&memoryConfig.LogSettings, nil, config.GetLogFileLocation)
+ if errCfg := testLogger.ConfigureTargets(logCfg); errCfg != nil {
+ panic("failed to configure test logger: " + errCfg.Error())
+ }
+ // lock logger config so server init cannot override it during testing.
+ testLogger.LockConfiguration()
+ options = append(options, app.SetLogger(testLogger))
+
s, err := app.NewServer(options...)
if err != nil {
panic(err)
@@ -131,6 +141,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
ConfigStore: configStore,
IncludeCacheLayer: includeCache,
Context: &request.Context{},
+ TestLogger: testLogger,
}
if s.SearchEngine != nil && s.SearchEngine.BleveEngine != nil && searchEngine != nil {
@@ -336,15 +347,11 @@ func (th *TestHelper) ShutdownApp() {
}
func (th *TestHelper) TearDown() {
- utils.DisableDebugLogForTest()
if th.IncludeCacheLayer {
// Clean all the caches
th.App.Srv().InvalidateAllCaches()
}
-
th.ShutdownApp()
-
- utils.EnableDebugLogForTest()
}
var initBasicOnce sync.Once
@@ -501,12 +508,10 @@ func (th *TestHelper) CreateBotWithClient(client *model.Client4) *model.Bot {
Description: "bot",
}
- utils.DisableDebugLogForTest()
rbot, _, err := client.CreateBot(bot)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return rbot
}
@@ -527,12 +532,10 @@ func (th *TestHelper) CreateTeamWithClient(client *model.Client4) *model.Team {
Type: model.TeamOpen,
}
- utils.DisableDebugLogForTest()
rteam, _, err := client.CreateTeam(team)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return rteam
}
@@ -548,7 +551,6 @@ func (th *TestHelper) CreateUserWithClient(client *model.Client4) *model.User {
Password: "Pa$$word11",
}
- utils.DisableDebugLogForTest()
ruser, _, err := client.CreateUser(user)
if err != nil {
panic(err)
@@ -559,7 +561,6 @@ func (th *TestHelper) CreateUserWithClient(client *model.Client4) *model.User {
if err != nil {
return nil
}
- utils.EnableDebugLogForTest()
return ruser
}
@@ -651,12 +652,10 @@ func (th *TestHelper) CreateChannelWithClientAndTeam(client *model.Client4, chan
TeamId: teamId,
}
- utils.DisableDebugLogForTest()
rchannel, _, err := client.CreateChannel(channel)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return rchannel
}
@@ -680,12 +679,10 @@ func (th *TestHelper) CreatePostWithClient(client *model.Client4, channel *model
Message: "message_" + id,
}
- utils.DisableDebugLogForTest()
rpost, _, err := client.CreatePost(post)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return rpost
}
@@ -698,12 +695,10 @@ func (th *TestHelper) CreatePinnedPostWithClient(client *model.Client4, channel
IsPinned: true,
}
- utils.DisableDebugLogForTest()
rpost, _, err := client.CreatePost(post)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return rpost
}
@@ -713,12 +708,10 @@ func (th *TestHelper) CreateMessagePostWithClient(client *model.Client4, channel
Message: message,
}
- utils.DisableDebugLogForTest()
rpost, _, err := client.CreatePost(post)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return rpost
}
@@ -738,13 +731,11 @@ func (th *TestHelper) CreateMessagePostNoClient(channel *model.Channel, message
}
func (th *TestHelper) CreateDmChannel(user *model.User) *model.Channel {
- utils.DisableDebugLogForTest()
var err *model.AppError
var channel *model.Channel
if channel, err = th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, user.Id); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
@@ -769,82 +760,59 @@ func (th *TestHelper) LoginSystemManager() {
}
func (th *TestHelper) LoginBasicWithClient(client *model.Client4) {
- utils.DisableDebugLogForTest()
_, _, err := client.Login(th.BasicUser.Email, th.BasicUser.Password)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) LoginBasic2WithClient(client *model.Client4) {
- utils.DisableDebugLogForTest()
_, _, err := client.Login(th.BasicUser2.Email, th.BasicUser2.Password)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) LoginTeamAdminWithClient(client *model.Client4) {
- utils.DisableDebugLogForTest()
_, _, err := client.Login(th.TeamAdminUser.Email, th.TeamAdminUser.Password)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) LoginSystemManagerWithClient(client *model.Client4) {
- utils.DisableDebugLogForTest()
_, _, err := client.Login(th.SystemManagerUser.Email, th.SystemManagerUser.Password)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) LoginSystemAdminWithClient(client *model.Client4) {
- utils.DisableDebugLogForTest()
_, _, err := client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) UpdateActiveUser(user *model.User, active bool) {
- utils.DisableDebugLogForTest()
-
_, err := th.App.UpdateActive(th.Context, user, active)
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
_, err := th.App.JoinUserToTeam(th.Context, team, user, "")
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember {
- utils.DisableDebugLogForTest()
-
member, err := th.App.AddUserToChannel(user, channel, false)
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
-
return member
}
@@ -864,12 +832,10 @@ func (th *TestHelper) CreateGroup() *model.Group {
RemoteId: "ri_" + id,
}
- utils.DisableDebugLogForTest()
group, err := th.App.CreateGroup(group)
if err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return group
}
@@ -1107,59 +1073,39 @@ func (th *TestHelper) cleanupTestFile(info *model.FileInfo) error {
}
func (th *TestHelper) MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
- utils.DisableDebugLogForTest()
-
if cm, err := th.App.Srv().Store.Channel().GetMember(context.Background(), channel.Id, user.Id); err == nil {
cm.SchemeAdmin = true
if _, err = th.App.Srv().Store.Channel().UpdateMember(cm); err != nil {
- utils.EnableDebugLogForTest()
panic(err)
}
} else {
- utils.EnableDebugLogForTest()
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
if tm, err := th.App.Srv().Store.Team().GetMember(context.Background(), team.Id, user.Id); err == nil {
tm.SchemeAdmin = true
if _, err = th.App.Srv().Store.Team().UpdateMember(tm); err != nil {
- utils.EnableDebugLogForTest()
panic(err)
}
} else {
- utils.EnableDebugLogForTest()
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) UpdateUserToNonTeamAdmin(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
if tm, err := th.App.Srv().Store.Team().GetMember(context.Background(), team.Id, user.Id); err == nil {
tm.SchemeAdmin = false
if _, err = th.App.Srv().Store.Team().UpdateMember(tm); err != nil {
- utils.EnableDebugLogForTest()
panic(err)
}
} else {
- utils.EnableDebugLogForTest()
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) SaveDefaultRolePermissions() map[string][]string {
- utils.DisableDebugLogForTest()
-
results := make(map[string][]string)
for _, roleName := range []string{
@@ -1172,24 +1118,18 @@ func (th *TestHelper) SaveDefaultRolePermissions() map[string][]string {
} {
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
results[roleName] = role.Permissions
}
-
- utils.EnableDebugLogForTest()
return results
}
func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
- utils.DisableDebugLogForTest()
-
for roleName, permissions := range data {
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
@@ -1201,20 +1141,14 @@ func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
@@ -1226,7 +1160,6 @@ func (th *TestHelper) RemovePermissionFromRole(permission string, roleName strin
}
if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
- utils.EnableDebugLogForTest()
return
}
@@ -1234,25 +1167,18 @@ func (th *TestHelper) RemovePermissionFromRole(permission string, roleName strin
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
for _, existingPermission := range role.Permissions {
if existingPermission == permission {
- utils.EnableDebugLogForTest()
return
}
}
@@ -1261,11 +1187,8 @@ func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) SetupTeamScheme() *model.Scheme {
diff --git a/api4/channel_test.go b/api4/channel_test.go
index 4be43f519e..fa82aa5aa8 100644
--- a/api4/channel_test.go
+++ b/api4/channel_test.go
@@ -21,7 +21,6 @@ import (
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin/plugintest/mock"
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
- "github.com/mattermost/mattermost-server/v6/utils"
)
func TestCreateChannel(t *testing.T) {
@@ -3238,7 +3237,6 @@ func TestAutocompleteChannels(t *testing.T) {
defer th.TearDown()
// A private channel to make sure private channels are not used
- utils.DisableDebugLogForTest()
ptown, _, _ := th.Client.CreateChannel(&model.Channel{
DisplayName: "Town",
Name: "town",
@@ -3251,7 +3249,6 @@ func TestAutocompleteChannels(t *testing.T) {
Type: model.ChannelTypeOpen,
TeamId: th.BasicTeam.Id,
})
- utils.EnableDebugLogForTest()
defer func() {
th.Client.DeleteChannel(ptown.Id)
th.Client.DeleteChannel(tower.Id)
@@ -3320,7 +3317,6 @@ func TestAutocompleteChannelsForSearch(t *testing.T) {
defer th.App.PermanentDeleteUser(th.Context, u4)
// A private channel to make sure private channels are not used
- utils.DisableDebugLogForTest()
ptown, _, _ := th.SystemAdminClient.CreateChannel(&model.Channel{
DisplayName: "Town",
Name: "town",
@@ -3339,7 +3335,6 @@ func TestAutocompleteChannelsForSearch(t *testing.T) {
defer func() {
th.Client.DeleteChannel(mypriv.Id)
}()
- utils.EnableDebugLogForTest()
dc1, _, err := th.Client.CreateDirectChannel(th.BasicUser.Id, u1.Id)
require.NoError(t, err)
@@ -3450,7 +3445,6 @@ func TestAutocompleteChannelsForSearchGuestUsers(t *testing.T) {
require.NoError(t, err)
// A private channel to make sure private channels are not used
- utils.DisableDebugLogForTest()
town, _, _ := th.SystemAdminClient.CreateChannel(&model.Channel{
DisplayName: "Town",
Name: "town",
@@ -3475,8 +3469,6 @@ func TestAutocompleteChannelsForSearchGuestUsers(t *testing.T) {
_, _, err = th.SystemAdminClient.AddChannelMember(mypriv.Id, guest.Id)
require.NoError(t, err)
- utils.EnableDebugLogForTest()
-
dc1, _, err := th.SystemAdminClient.CreateDirectChannel(th.BasicUser.Id, guest.Id)
require.NoError(t, err)
defer func() {
diff --git a/api4/config_test.go b/api4/config_test.go
index 53e9cf3405..3baaef649d 100644
--- a/api4/config_test.go
+++ b/api4/config_test.go
@@ -4,7 +4,6 @@
package api4
import (
- "context"
"fmt"
"io/ioutil"
"net/http"
@@ -468,7 +467,7 @@ func TestUpdateConfigDiffInAuditRecord(t *testing.T) {
require.Equal(t, timeoutVal+1, *cfg.ServiceSettings.ReadTimeout)
// Forcing a flush before attempting to read log's content.
- err = th.Server.Log.Flush(context.Background())
+ err = th.Server.Audit.Flush()
require.NoError(t, err)
require.NoError(t, logFile.Sync())
diff --git a/api4/main_test.go b/api4/main_test.go
index 90862a5886..961db24f07 100644
--- a/api4/main_test.go
+++ b/api4/main_test.go
@@ -7,7 +7,6 @@ import (
"flag"
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -25,8 +24,6 @@ func TestMain(m *testing.M) {
WithReadReplica: replicaFlag,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/api4/system_test.go b/api4/system_test.go
index 75e8474706..37c861c2e3 100644
--- a/api4/system_test.go
+++ b/api4/system_test.go
@@ -327,9 +327,12 @@ func TestGetLogs(t *testing.T) {
mlog.Info(strconv.Itoa(i))
}
+ err := th.TestLogger.Flush()
+ require.NoError(t, err, "failed to flush log")
+
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
- logs, _, err := c.GetLogs(0, 10)
- require.NoError(t, err)
+ logs, _, err2 := c.GetLogs(0, 10)
+ require.NoError(t, err2)
require.Len(t, logs, 10)
for i := 10; i < 20; i++ {
@@ -347,8 +350,8 @@ func TestGetLogs(t *testing.T) {
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
- _, resp, err := th.Client.GetLogs(0, 10)
- require.Error(t, err)
+ _, resp, err2 := th.Client.GetLogs(0, 10)
+ require.Error(t, err2)
CheckForbiddenStatus(t, resp)
})
diff --git a/app/admin.go b/app/admin.go
index bee56f5dc4..4b3fb3bf34 100644
--- a/app/admin.go
+++ b/app/admin.go
@@ -4,7 +4,6 @@
package app
import (
- "context"
"fmt"
"io"
"io/ioutil"
@@ -13,11 +12,11 @@ import (
"runtime/debug"
"time"
+ "github.com/mattermost/mattermost-server/v6/config"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/i18n"
"github.com/mattermost/mattermost-server/v6/shared/mail"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
- "github.com/mattermost/mattermost-server/v6/utils"
)
func (s *Server) GetLogs(page, perPage int) ([]string, *model.AppError) {
@@ -63,11 +62,8 @@ func (s *Server) GetLogsSkipSend(page, perPage int) ([]string, *model.AppError)
var lines []string
if *s.Config().LogSettings.EnableFile {
- timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), mlog.DefaultFlushTimeout)
- defer timeoutCancel()
- mlog.Flush(timeoutCtx)
-
- logFile := utils.GetLogFileLocation(*s.Config().LogSettings.FileLocation)
+ s.Log.Flush()
+ logFile := config.GetLogFileLocation(*s.Config().LogSettings.FileLocation)
file, err := os.Open(logFile)
if err != nil {
return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError)
diff --git a/app/app_iface.go b/app/app_iface.go
index 60a0f04a79..a39162fc3e 100644
--- a/app/app_iface.go
+++ b/app/app_iface.go
@@ -232,7 +232,7 @@ type AppIface interface {
// LogAuditRec logs an audit record using default LvlAuditCLI.
LogAuditRec(rec *audit.Record, err error)
// LogAuditRecWithLevel logs an audit record using specified Level.
- LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel, err error)
+ LogAuditRecWithLevel(rec *audit.Record, level mlog.Level, err error)
// MakeAuditRecord creates a audit record pre-populated with defaults.
MakeAuditRecord(event string, initialStatus string) *audit.Record
// MarkChanelAsUnreadFromPost will take a post and set the channel as unread from that one.
diff --git a/app/audit.go b/app/audit.go
index 845a2ee35e..a1a8837094 100644
--- a/app/audit.go
+++ b/app/audit.go
@@ -9,8 +9,6 @@ import (
"net/http"
"os/user"
- "github.com/hashicorp/go-multierror"
-
"github.com/mattermost/mattermost-server/v6/audit"
"github.com/mattermost/mattermost-server/v6/config"
"github.com/mattermost/mattermost-server/v6/model"
@@ -66,7 +64,7 @@ func (a *App) LogAuditRec(rec *audit.Record, err error) {
}
// LogAuditRecWithLevel logs an audit record using specified Level.
-func (a *App) LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel, err error) {
+func (a *App) LogAuditRecWithLevel(rec *audit.Record, level mlog.Level, err error) {
if rec == nil {
return
}
@@ -106,64 +104,27 @@ func (a *App) MakeAuditRecord(event string, initialStatus string) *audit.Record
}
func (s *Server) configureAudit(adt *audit.Audit, bAllowAdvancedLogging bool) error {
- var errs error
-
adt.OnQueueFull = s.onAuditTargetQueueFull
adt.OnError = s.onAuditError
- // Configure target for rotating file output (E0, E10)
- if *s.Config().ExperimentalAuditSettings.FileEnabled {
- opts := audit.FileOptions{
- Filename: *s.Config().ExperimentalAuditSettings.FileName,
- MaxSize: *s.Config().ExperimentalAuditSettings.FileMaxSizeMB,
- MaxAge: *s.Config().ExperimentalAuditSettings.FileMaxAgeDays,
- MaxBackups: *s.Config().ExperimentalAuditSettings.FileMaxBackups,
- Compress: *s.Config().ExperimentalAuditSettings.FileCompress,
- }
-
- maxQueueSize := *s.Config().ExperimentalAuditSettings.FileMaxQueueSize
- if maxQueueSize <= 0 {
- maxQueueSize = audit.DefMaxQueueSize
- }
-
- filter := adt.MakeFilter(LevelAPI, LevelContent, LevelPerms, LevelCLI)
- formatter := adt.MakeJSONFormatter()
- formatter.DisableTimestamp = false
- target, err := audit.NewFileTarget(filter, formatter, opts, maxQueueSize)
- if err != nil {
- errs = multierror.Append(err)
- } else {
- mlog.Debug("File audit target created successfully", mlog.String("filename", opts.Filename))
- adt.AddTarget(target)
- }
- }
-
- // Advanced logging for audit requires license.
+ var logConfigSrc config.LogConfigSrc
dsn := *s.Config().ExperimentalAuditSettings.AdvancedLoggingConfig
- if !bAllowAdvancedLogging || dsn == "" {
- return errs
- }
- cfg, err := config.NewLogConfigSrc(dsn, s.configStore)
- if err != nil {
- errs = multierror.Append(fmt.Errorf("invalid config for audit, %w", err))
- return errs
- }
- mlog.Debug("Loaded audit configuration", mlog.String("source", dsn))
-
- for name, t := range cfg.Get() {
- if len(t.Levels) == 0 {
- t.Levels = mlog.MLvlAuditAll
- }
- target, err := mlog.NewLogrTarget(name, t)
+ if bAllowAdvancedLogging && dsn != "" {
+ var err error
+ logConfigSrc, err = config.NewLogConfigSrc(dsn, s.configStore)
if err != nil {
- errs = multierror.Append(err)
- continue
- }
- if target != nil {
- adt.AddTarget(target)
+ return fmt.Errorf("invalid config source for audit, %w", err)
}
+ mlog.Debug("Loaded audit configuration", mlog.String("source", dsn))
}
- return errs
+
+ // ExperimentalAuditSettings provides basic file audit (E0, E10); logConfigSrc provides advanced config (E20).
+ cfg, err := config.MloggerConfigFromAuditConfig(s.Config().ExperimentalAuditSettings, logConfigSrc)
+ if err != nil {
+ return fmt.Errorf("invalid config for audit, %w", err)
+ }
+
+ return adt.Configure(cfg)
}
func (s *Server) onAuditTargetQueueFull(qname string, maxQSize int) bool {
diff --git a/app/email/helper_test.go b/app/email/helper_test.go
index 4405e2e15f..f61401d91b 100644
--- a/app/email/helper_test.go
+++ b/app/email/helper_test.go
@@ -19,7 +19,6 @@ import (
"github.com/mattermost/mattermost-server/v6/store"
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
"github.com/mattermost/mattermost-server/v6/testlib"
- "github.com/mattermost/mattermost-server/v6/utils"
)
type TestHelper struct {
@@ -172,12 +171,10 @@ func (th *TestHelper) CreateTeam() *model.Team {
Type: model.TeamOpen,
}
- utils.DisableDebugLogForTest()
var err error
if team, err = th.store.Team().Save(team); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return team
}
@@ -192,13 +189,11 @@ func (th *TestHelper) createChannel(team *model.Team, channelType string) *model
CreatorId: th.BasicUser.Id,
}
- utils.DisableDebugLogForTest()
var err error
if channel, err = th.store.Channel().Save(channel, *th.configStore.Get().TeamSettings.MaxChannelsPerTeam); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
diff --git a/app/email/main_test.go b/app/email/main_test.go
index 587877f33d..ef8941c6d1 100644
--- a/app/email/main_test.go
+++ b/app/email/main_test.go
@@ -7,7 +7,6 @@ import (
"flag"
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -26,8 +25,6 @@ func TestMain(m *testing.M) {
WithReadReplica: replicaFlag,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/app/file_bench_test.go b/app/file_bench_test.go
index 44c7516851..515f69cc03 100644
--- a/app/file_bench_test.go
+++ b/app/file_bench_test.go
@@ -16,7 +16,6 @@ import (
"time"
"github.com/mattermost/mattermost-server/v6/model"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
)
var randomJPEG []byte
@@ -59,8 +58,7 @@ func BenchmarkUploadFile(b *testing.B) {
prepareTestImages(b)
th := Setup(b).InitBasic()
defer th.TearDown()
- // disable logging in the benchmark, as best we can
- th.App.Log().SetConsoleLevel(mlog.LevelError)
+
teamID := model.NewId()
channelID := model.NewId()
userID := model.NewId()
diff --git a/app/helper_test.go b/app/helper_test.go
index febb49fda7..c491eda57f 100644
--- a/app/helper_test.go
+++ b/app/helper_test.go
@@ -4,7 +4,6 @@
package app
import (
- "bytes"
"context"
"io/ioutil"
"os"
@@ -27,7 +26,6 @@ import (
"github.com/mattermost/mattermost-server/v6/store/sqlstore"
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
"github.com/mattermost/mattermost-server/v6/testlib"
- "github.com/mattermost/mattermost-server/v6/utils"
)
type TestHelper struct {
@@ -41,7 +39,8 @@ type TestHelper struct {
BasicPost *model.Post
SystemAdminUser *model.User
- LogBuffer *bytes.Buffer
+ LogBuffer *mlog.Buffer
+ TestLogger *mlog.Logger
IncludeCacheLayer bool
tempWorkspace string
@@ -55,16 +54,16 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
configStore := config.NewTestMemoryStore()
- config := configStore.Get()
- *config.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
- *config.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
- *config.PluginSettings.AutomaticPrepackagedPlugins = false
- *config.LogSettings.EnableSentry = false // disable error reporting during tests
- *config.AnnouncementSettings.AdminNoticesEnabled = false
- *config.AnnouncementSettings.UserNoticesEnabled = false
- configStore.Set(config)
+ memoryConfig := configStore.Get()
+ *memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
+ *memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
+ *memoryConfig.PluginSettings.AutomaticPrepackagedPlugins = false
+ *memoryConfig.LogSettings.EnableSentry = false // disable error reporting during tests
+ *memoryConfig.AnnouncementSettings.AdminNoticesEnabled = false
+ *memoryConfig.AnnouncementSettings.UserNoticesEnabled = false
+ configStore.Set(memoryConfig)
- buffer := &bytes.Buffer{}
+ buffer := &mlog.Buffer{}
var options []Option
options = append(options, ConfigStore(configStore))
@@ -80,7 +79,18 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
} else {
options = append(options, StoreOverride(dbStore))
}
- options = append(options, SetLogger(mlog.NewTestingLogger(tb, buffer)))
+
+ testLogger, _ := mlog.NewLogger()
+ logCfg, _ := config.MloggerConfigFromLoggerConfig(&memoryConfig.LogSettings, nil, config.GetLogFileLocation)
+ if errCfg := testLogger.ConfigureTargets(logCfg); errCfg != nil {
+ panic("failed to configure test logger: " + errCfg.Error())
+ }
+ if errW := mlog.AddWriterTarget(testLogger, buffer, true, mlog.StdAll...); errW != nil {
+ panic("failed to add writer target to test logger: " + errW.Error())
+ }
+ // lock logger config so server init cannot override it during testing.
+ testLogger.LockConfiguration()
+ options = append(options, SetLogger(testLogger))
s, err := NewServer(options...)
if err != nil {
@@ -92,6 +102,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
Context: &request.Context{},
Server: s,
LogBuffer: buffer,
+ TestLogger: testLogger,
IncludeCacheLayer: includeCacheLayer,
}
@@ -240,12 +251,10 @@ func (th *TestHelper) CreateTeam() *model.Team {
Type: model.TeamOpen,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if team, err = th.App.CreateTeam(th.Context, team); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return team
}
@@ -268,7 +277,6 @@ func (th *TestHelper) CreateUserOrGuest(guest bool) *model.User {
EmailVerified: true,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if guest {
if user, err = th.App.CreateGuest(th.Context, user); err != nil {
@@ -279,7 +287,6 @@ func (th *TestHelper) CreateUserOrGuest(guest bool) *model.User {
panic(err)
}
}
- utils.EnableDebugLogForTest()
return user
}
@@ -331,7 +338,6 @@ func (th *TestHelper) createChannel(team *model.Team, channelType model.ChannelT
option(channel)
}
- utils.DisableDebugLogForTest()
var appErr *model.AppError
if channel, appErr = th.App.CreateChannel(th.Context, channel, true); appErr != nil {
panic(appErr)
@@ -353,29 +359,24 @@ func (th *TestHelper) createChannel(team *model.Team, channelType model.ChannelT
panic(err)
}
}
- utils.EnableDebugLogForTest()
return channel
}
func (th *TestHelper) CreateDmChannel(user *model.User) *model.Channel {
- utils.DisableDebugLogForTest()
var err *model.AppError
var channel *model.Channel
if channel, err = th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, user.Id); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
func (th *TestHelper) CreateGroupChannel(user1 *model.User, user2 *model.User) *model.Channel {
- utils.DisableDebugLogForTest()
var err *model.AppError
var channel *model.Channel
if channel, err = th.App.CreateGroupChannel([]string{th.BasicUser.Id, user1.Id, user2.Id}, th.BasicUser.Id); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
@@ -389,12 +390,10 @@ func (th *TestHelper) CreatePost(channel *model.Channel) *model.Post {
CreateAt: model.GetMillis() - 10000,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if post, err = th.App.CreatePost(th.Context, post, channel, false, true); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return post
}
@@ -406,47 +405,32 @@ func (th *TestHelper) CreateMessagePost(channel *model.Channel, message string)
CreateAt: model.GetMillis() - 10000,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if post, err = th.App.CreatePost(th.Context, post, channel, false, true); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return post
}
func (th *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
_, err := th.App.JoinUserToTeam(th.Context, team, user, "")
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) RemoveUserFromTeam(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
err := th.App.RemoveUserFromTeam(th.Context, team.Id, user.Id, "")
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember {
- utils.DisableDebugLogForTest()
-
member, err := th.App.AddUserToChannel(user, channel, false)
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
-
return member
}
@@ -456,8 +440,6 @@ func (th *TestHelper) CreateRole(roleName string) *model.Role {
}
func (th *TestHelper) CreateScheme() (*model.Scheme, []*model.Role) {
- utils.DisableDebugLogForTest()
-
scheme, err := th.App.CreateScheme(&model.Scheme{
DisplayName: "Test Scheme Display Name",
Name: model.NewId(),
@@ -485,9 +467,6 @@ func (th *TestHelper) CreateScheme() (*model.Scheme, []*model.Role) {
}
roles = append(roles, role)
}
-
- utils.EnableDebugLogForTest()
-
return scheme, roles
}
@@ -501,18 +480,14 @@ func (th *TestHelper) CreateGroup() *model.Group {
RemoteId: model.NewId(),
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if group, err = th.App.CreateGroup(group); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return group
}
func (th *TestHelper) CreateEmoji() *model.Emoji {
- utils.DisableDebugLogForTest()
-
emoji, err := th.App.Srv().Store.Emoji().Save(&model.Emoji{
CreatorId: th.BasicUser.Id,
Name: model.NewRandomString(10),
@@ -520,15 +495,10 @@ func (th *TestHelper) CreateEmoji() *model.Emoji {
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
-
return emoji
}
func (th *TestHelper) AddReactionToPost(post *model.Post, user *model.User, emojiName string) *model.Reaction {
- utils.DisableDebugLogForTest()
-
reaction, err := th.App.SaveReactionForPost(th.Context, &model.Reaction{
UserId: user.Id,
PostId: post.Id,
@@ -537,9 +507,6 @@ func (th *TestHelper) AddReactionToPost(post *model.Post, user *model.User, emoj
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
-
return reaction
}
@@ -668,11 +635,8 @@ func (th *TestHelper) SetupPluginAPI() *PluginAPI {
}
func (th *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
@@ -684,7 +648,6 @@ func (th *TestHelper) RemovePermissionFromRole(permission string, roleName strin
}
if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
- utils.EnableDebugLogForTest()
return
}
@@ -692,25 +655,18 @@ func (th *TestHelper) RemovePermissionFromRole(permission string, roleName strin
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
for _, existingPermission := range role.Permissions {
if existingPermission == permission {
- utils.EnableDebugLogForTest()
return
}
}
@@ -719,11 +675,8 @@ func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
// This function is copy of storetest/NewTestId
diff --git a/app/main_test.go b/app/main_test.go
index 486e7d6b30..10af131a62 100644
--- a/app/main_test.go
+++ b/app/main_test.go
@@ -7,7 +7,6 @@ import (
"flag"
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -26,8 +25,6 @@ func TestMain(m *testing.M) {
WithReadReplica: replicaFlag,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go
index e2377b2625..3947de1ec7 100644
--- a/app/opentracing/opentracing_layer.go
+++ b/app/opentracing/opentracing_layer.go
@@ -11251,7 +11251,7 @@ func (a *OpenTracingAppLayer) LogAuditRec(rec *audit.Record, err error) {
a.app.LogAuditRec(rec, err)
}
-func (a *OpenTracingAppLayer) LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel, err error) {
+func (a *OpenTracingAppLayer) LogAuditRecWithLevel(rec *audit.Record, level mlog.Level, err error) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.LogAuditRecWithLevel")
diff --git a/app/plugin_api.go b/app/plugin_api.go
index c1594060ec..90d648d709 100644
--- a/app/plugin_api.go
+++ b/app/plugin_api.go
@@ -25,7 +25,7 @@ type PluginAPI struct {
id string
app *App
ctx *request.Context
- logger *mlog.SugarLogger
+ logger mlog.Sugar
manifest *model.Manifest
}
@@ -35,7 +35,7 @@ func NewPluginAPI(a *App, c *request.Context, manifest *model.Manifest) *PluginA
manifest: manifest,
ctx: c,
app: a,
- logger: a.Log().With(mlog.String("plugin_id", manifest.Id)).Sugar(),
+ logger: a.Log().Sugar(mlog.String("plugin_id", manifest.Id)),
}
}
diff --git a/app/plugin_test.go b/app/plugin_test.go
index 4bea22c030..c85f4f61b2 100644
--- a/app/plugin_test.go
+++ b/app/plugin_test.go
@@ -724,11 +724,14 @@ func TestPluginPanicLogs(t *testing.T) {
}
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, false, true)
assert.Nil(t, err)
+
+ th.TestLogger.Flush()
+
// We shutdown plugins first so that the read on the log buffer is race-free.
th.App.Srv().ShutDownPlugins()
tearDown()
- testlib.AssertLog(t, th.LogBuffer, mlog.LevelDebug, "panic: some text from panic")
+ testlib.AssertLog(t, th.LogBuffer, mlog.LvlDebug.Name, "panic: some text from panic")
})
}
diff --git a/app/post_test.go b/app/post_test.go
index d60bfb89c7..0654f30667 100644
--- a/app/post_test.go
+++ b/app/post_test.go
@@ -970,7 +970,7 @@ func TestCreatePostAsUser(t *testing.T) {
_, appErr := th.App.CreatePostAsUser(th.Context, post, "", true)
require.Nil(t, appErr)
- testlib.AssertLog(t, th.LogBuffer, mlog.LevelWarn, "Failed to get membership")
+ testlib.AssertLog(t, th.LogBuffer, mlog.LvlWarn.Name, "Failed to get membership")
})
t.Run("does not log warning for bot user not in channel", func(t *testing.T) {
@@ -993,7 +993,7 @@ func TestCreatePostAsUser(t *testing.T) {
_, appErr = th.App.CreatePostAsUser(th.Context, post, "", true)
require.Nil(t, appErr)
- testlib.AssertNoLog(t, th.LogBuffer, mlog.LevelWarn, "Failed to get membership")
+ testlib.AssertNoLog(t, th.LogBuffer, mlog.LvlWarn.Name, "Failed to get membership")
})
t.Run("marks channel as viewed for reply post when CRT is off", func(t *testing.T) {
diff --git a/app/server.go b/app/server.go
index a0f4e86b5c..edb3286726 100644
--- a/app/server.go
+++ b/app/server.go
@@ -138,7 +138,6 @@ type Server struct {
statusCache cache.Cache
configListenerId string
licenseListenerId string
- logListenerId string
clusterLeaderListenerId string
searchConfigListenerId string
searchLicenseListenerId string
@@ -146,8 +145,6 @@ type Server struct {
configStore *config.Store
postActionCookieSecret []byte
- advancedLogListenerCleanup func()
-
pluginCommands []*PluginCommand
pluginCommandsLock sync.RWMutex
@@ -787,74 +784,79 @@ func (s *Server) DatabaseTypeAndMattermostVersion() (string, string) {
return *s.Config().SqlSettings.DriverName, mattermostVersion.Value
}
-// initLogging initializes and configures the logger. This may be called more than once.
+// initLogging initializes and configures the logger(s). This may be called more than once.
func (s *Server) initLogging() error {
+ var err error
+ // create the app logger if needed
if s.Log == nil {
- s.Log = mlog.NewLogger(utils.MloggerConfigFromLoggerConfig(&s.Config().LogSettings, utils.GetLogFileLocation))
- }
-
- // Use this app logger as the global logger (eventually remove all instances of global logging).
- // This is deferred because a copy is made of the logger and it must be fully configured before
- // the copy is made.
- defer mlog.InitGlobalLogger(s.Log)
-
- // Redirect default Go logger to this logger.
- defer mlog.RedirectStdLog(s.Log)
-
- if s.NotificationsLog == nil {
- notificationLogSettings := utils.GetLogSettingsFromNotificationsLogSettings(&s.Config().NotificationLogSettings)
- s.NotificationsLog = mlog.NewLogger(utils.MloggerConfigFromLoggerConfig(notificationLogSettings, utils.GetNotificationsLogFileLocation)).
- WithCallerSkip(1).With(mlog.String("logSource", "notifications"))
- }
-
- if s.logListenerId != "" {
- s.RemoveConfigListener(s.logListenerId)
- }
- s.logListenerId = s.AddConfigListener(func(_, after *model.Config) {
- s.Log.ChangeLevels(utils.MloggerConfigFromLoggerConfig(&after.LogSettings, utils.GetLogFileLocation))
-
- notificationLogSettings := utils.GetLogSettingsFromNotificationsLogSettings(&after.NotificationLogSettings)
- s.NotificationsLog.ChangeLevels(utils.MloggerConfigFromLoggerConfig(notificationLogSettings, utils.GetNotificationsLogFileLocation))
- })
-
- // Configure advanced logging.
- // Advanced logging is E20 only, however logging must be initialized before the license
- // file is loaded. If no valid E20 license exists then advanced logging will be
- // shutdown once license is loaded/checked.
- if *s.Config().LogSettings.AdvancedLoggingConfig != "" {
- dsn := *s.Config().LogSettings.AdvancedLoggingConfig
-
- cfg, err := config.NewLogConfigSrc(dsn, s.configStore)
+ s.Log, err = mlog.NewLogger()
if err != nil {
- return fmt.Errorf("invalid advanced logging config, %w", err)
+ return err
}
+ }
- if err := s.Log.ConfigAdvancedLogging(cfg.Get()); err != nil {
- return fmt.Errorf("error configuring advanced logging, %w", err)
+ // create notification logger if needed
+ if s.NotificationsLog == nil {
+ l, err := mlog.NewLogger()
+ if err != nil {
+ return err
}
+ s.NotificationsLog = l.With(mlog.String("logSource", "notifications"))
+ }
- mlog.Info("Loaded advanced logging config", mlog.String("source", dsn))
-
- listenerId := cfg.AddListener(func(_, newCfg mlog.LogTargetCfg) {
- if err := s.Log.ConfigAdvancedLogging(newCfg); err != nil {
- mlog.Error("Error re-configuring advanced logging", mlog.Err(err))
- } else {
- mlog.Info("Re-configured advanced logging")
- }
- })
-
- // In case initLogging is called more than once.
- if s.advancedLogListenerCleanup != nil {
- s.advancedLogListenerCleanup()
+ if err := s.configureLogger("logging", s.Log, &s.Config().LogSettings, s.configStore, config.GetLogFileLocation); err != nil {
+ // if the config is locked then a unit test has already configured and locked the logger; not an error.
+ if !errors.Is(err, mlog.ErrConfigurationLock) {
+ // revert to default logger if the config is invalid
+ mlog.InitGlobalLogger(nil)
+ return err
}
+ }
- s.advancedLogListenerCleanup = func() {
- cfg.RemoveListener(listenerId)
+ // Redirect default Go logger to app logger.
+ s.Log.RedirectStdLog(mlog.LvlStdLog)
+
+ // Use the app logger as the global logger (eventually remove all instances of global logging).
+ mlog.InitGlobalLogger(s.Log)
+
+ notificationLogSettings := config.GetLogSettingsFromNotificationsLogSettings(&s.Config().NotificationLogSettings)
+ if err := s.configureLogger("notification logging", s.NotificationsLog, notificationLogSettings, s.configStore, config.GetNotificationsLogFileLocation); err != nil {
+ if !errors.Is(err, mlog.ErrConfigurationLock) {
+ mlog.Error("Error configuring notification logger", mlog.Err(err))
+ return err
}
}
return nil
}
+// configureLogger applies the specified configuration to a logger.
+func (s *Server) configureLogger(name string, logger *mlog.Logger, logSettings *model.LogSettings, configStore *config.Store, getPath func(string) string) error {
+ // Advanced logging is E20 only, however logging must be initialized before the license
+ // file is loaded. If no valid E20 license exists then advanced logging will be
+ // shutdown once license is loaded/checked.
+ var err error
+ dsn := *logSettings.AdvancedLoggingConfig
+ var logConfigSrc config.LogConfigSrc
+ if dsn != "" {
+ logConfigSrc, err = config.NewLogConfigSrc(dsn, configStore)
+ if err != nil {
+ return fmt.Errorf("invalid config source for %s, %w", name, err)
+ }
+ mlog.Info("Loaded configuration for "+name, mlog.String("source", dsn))
+ }
+
+ cfg, err := config.MloggerConfigFromLoggerConfig(logSettings, logConfigSrc, getPath)
+ if err != nil {
+ return fmt.Errorf("invalid config source for %s, %w", name, err)
+ }
+
+ if err := logger.ConfigureTargets(cfg); err != nil {
+ return fmt.Errorf("invalid config for %s, %w", name, err)
+ }
+ return nil
+}
+
+// removeUnlicensedLogTargets removes any unlicensed log target types.
func (s *Server) removeUnlicensedLogTargets(license *model.License) {
if license != nil && *license.Features.AdvancedLogging {
// advanced logging enabled via license; no need to remove any targets
@@ -864,8 +866,12 @@ func (s *Server) removeUnlicensedLogTargets(license *model.License) {
timeoutCtx, cancelCtx := context.WithTimeout(context.Background(), time.Second*10)
defer cancelCtx()
- mlog.RemoveTargets(timeoutCtx, func(ti mlog.TargetInfo) bool {
- return ti.Type != "*target.Writer" && ti.Type != "*target.File"
+ s.Log.RemoveTargets(timeoutCtx, func(ti mlog.TargetInfo) bool {
+ return ti.Type != "*targets.Writer" && ti.Type != "*targets.File"
+ })
+
+ s.NotificationsLog.RemoveTargets(timeoutCtx, func(ti mlog.TargetInfo) bool {
+ return ti.Type != "*targets.Writer" && ti.Type != "*targets.File"
})
}
@@ -939,11 +945,15 @@ func (s *Server) enableLoggingMetrics() {
return
}
- if err := mlog.EnableMetrics(s.Metrics.GetLoggerMetricsCollector()); err != nil {
- mlog.Error("Failed to enable advanced logging metrics", mlog.Err(err))
- } else {
- mlog.Debug("Advanced logging metrics enabled")
+ s.Log.SetMetricsCollector(s.Metrics.GetLoggerMetricsCollector(), mlog.DefaultMetricsUpdateFreqMillis)
+
+ // logging config needs to be reloaded when metrics collector is added or changed.
+ if err := s.initLogging(); err != nil {
+ mlog.Error("Error re-configuring logging for metrics")
+ return
}
+
+ mlog.Debug("Logging metrics enabled")
}
const TimeToWaitForConnectionsToCloseOnServerShutdown = time.Second
@@ -1014,13 +1024,7 @@ func (s *Server) Shutdown() {
s.WaitForGoroutines()
- if s.advancedLogListenerCleanup != nil {
- s.advancedLogListenerCleanup()
- s.advancedLogListenerCleanup = nil
- }
-
s.RemoveConfigListener(s.configListenerId)
- s.RemoveConfigListener(s.logListenerId)
s.stopSearchEngine()
s.Audit.Shutdown()
@@ -1058,12 +1062,6 @@ func (s *Server) Shutdown() {
}
}
- timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), time.Second*15)
- defer timeoutCancel()
- if err := mlog.Flush(timeoutCtx); err != nil {
- mlog.Warn("Error flushing logs", mlog.Err(err))
- }
-
s.dndTaskMut.Lock()
if s.dndTask != nil {
s.dndTask.Cancel()
@@ -1072,10 +1070,15 @@ func (s *Server) Shutdown() {
mlog.Info("Server stopped")
- // this should just write the "server stopped" record, the rest are already flushed.
- timeoutCtx2, timeoutCancel2 := context.WithTimeout(context.Background(), time.Second*5)
- defer timeoutCancel2()
- _ = mlog.ShutdownAdvancedLogging(timeoutCtx2)
+ // shutdown main and notification loggers which will flush any remaining log records.
+ timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), time.Second*15)
+ defer timeoutCancel()
+ if err = s.NotificationsLog.ShutdownWithTimeout(timeoutCtx); err != nil {
+ fmt.Fprintf(os.Stderr, "Error shutting down notification logger: %v", err)
+ }
+ if err = s.Log.ShutdownWithTimeout(timeoutCtx); err != nil {
+ fmt.Fprintf(os.Stderr, "Error shutting down main logger: %v", err)
+ }
}
func (s *Server) Restart() error {
@@ -1202,7 +1205,7 @@ func (s *Server) Start() error {
// If we have debugging of CORS turned on then forward messages to logs
if debug {
- corsWrapper.Log = s.Log.StdLog(mlog.String("source", "cors"))
+ corsWrapper.Log = s.Log.With(mlog.String("source", "cors")).StdLogger(mlog.LvlDebug)
}
handler = corsWrapper.Handler(handler)
@@ -1222,10 +1225,7 @@ func (s *Server) Start() error {
s.Busy = NewBusy(s.Cluster)
// Creating a logger for logging errors from http.Server at error level
- errStdLog, err := s.Log.StdLogAt(mlog.LevelError, mlog.String("source", "httpserver"))
- if err != nil {
- return err
- }
+ errStdLog := s.Log.With(mlog.String("source", "httpserver")).StdLogger(mlog.LvlError)
s.Server = &http.Server{
Handler: handler,
@@ -1270,7 +1270,7 @@ func (s *Server) Start() error {
server := &http.Server{
Addr: httpListenAddress,
Handler: m.HTTPHandler(nil),
- ErrorLog: s.Log.StdLog(mlog.String("source", "le_forwarder_server")),
+ ErrorLog: s.Log.With(mlog.String("source", "le_forwarder_server")).StdLogger(mlog.LvlError),
}
go server.ListenAndServe()
} else {
@@ -1284,7 +1284,7 @@ func (s *Server) Start() error {
server := &http.Server{
Handler: http.HandlerFunc(handleHTTPRedirect),
- ErrorLog: s.Log.StdLog(mlog.String("source", "forwarder_server")),
+ ErrorLog: s.Log.With(mlog.String("source", "forwarder_server")).StdLogger(mlog.LvlError),
}
server.Serve(redirectListener)
}()
@@ -2026,7 +2026,7 @@ func (a *App) getNotificationsLog() (*model.FileData, string) {
// Getting notifications.log
if *a.Srv().Config().NotificationLogSettings.EnableFile {
// notifications.log
- notificationsLog := utils.GetNotificationsLogFileLocation(*a.Srv().Config().LogSettings.FileLocation)
+ notificationsLog := config.GetNotificationsLogFileLocation(*a.Srv().Config().LogSettings.FileLocation)
notificationsLogFileData, notificationsLogFileDataErr := ioutil.ReadFile(notificationsLog)
@@ -2053,7 +2053,7 @@ func (a *App) getMattermostLog() (*model.FileData, string) {
// Getting mattermost.log
if *a.Srv().Config().LogSettings.EnableFile {
// mattermost.log
- mattermostLog := utils.GetLogFileLocation(*a.Srv().Config().LogSettings.FileLocation)
+ mattermostLog := config.GetLogFileLocation(*a.Srv().Config().LogSettings.FileLocation)
mattermostLogFileData, mattermostLogFileDataErr := ioutil.ReadFile(mattermostLog)
diff --git a/app/server_test.go b/app/server_test.go
index 0c61209f32..4016847bdd 100644
--- a/app/server_test.go
+++ b/app/server_test.go
@@ -516,29 +516,29 @@ func checkEndpoint(t *testing.T, client *http.Client, url string) error {
}
func TestPanicLog(t *testing.T) {
- // Creating a temp file to collect logs
- tmpfile, err := ioutil.TempFile("", "mlog")
- if err != nil {
- require.NoError(t, err)
- }
-
+ // Creating a temp dir for log
+ tmpDir, err := os.MkdirTemp("", "mlog-test")
+ require.NoError(t, err, "cannot create tmp dir for log file")
defer func() {
- require.NoError(t, tmpfile.Close())
- require.NoError(t, os.Remove(tmpfile.Name()))
+ err2 := os.RemoveAll(tmpDir)
+ assert.NoError(t, err2)
}()
- // This test requires Zap file target for now.
- mlog.EnableZap()
- defer mlog.DisableZap()
-
// Creating logger to log to console and temp file
- logger := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- EnableFile: true,
- FileLocation: tmpfile.Name(),
- FileLevel: mlog.LevelInfo,
- })
+ logger, _ := mlog.NewLogger()
+
+ logSettings := model.NewLogSettings()
+ logSettings.EnableConsole = model.NewBool(true)
+ logSettings.ConsoleJson = model.NewBool(true)
+ logSettings.EnableFile = model.NewBool(true)
+ logSettings.FileLocation = &tmpDir
+ logSettings.FileLevel = &mlog.LvlInfo.Name
+
+ cfg, err := config.MloggerConfigFromLoggerConfig(logSettings, nil, config.GetLogFileLocation)
+ require.NoError(t, err)
+ err = logger.ConfigureTargets(cfg)
+ require.NoError(t, err)
+ logger.LockConfiguration()
// Creating a server with logger
s, err := NewServer(SetLogger(logger))
@@ -567,16 +567,22 @@ func TestPanicLog(t *testing.T) {
client := &http.Client{Transport: tr}
client.Get("https://localhost:" + strconv.Itoa(s.ListenAddr.Port) + "/panic")
+
+ err = logger.Flush()
+ assert.NoError(t, err, "flush should succeed")
s.Shutdown()
// Checking whether panic was logged
var panicLogged = false
var infoLogged = false
- _, err = tmpfile.Seek(0, 0)
+ logFile, err := os.Open(config.GetLogFileLocation(tmpDir))
+ require.NoError(t, err, "cannot open log file")
+
+ _, err = logFile.Seek(0, 0)
require.NoError(t, err)
- scanner := bufio.NewScanner(tmpfile)
+ scanner := bufio.NewScanner(logFile)
for scanner.Scan() {
if !infoLogged && strings.Contains(scanner.Text(), "inside panic handler") {
infoLogged = true
diff --git a/app/slashcommands/helper_test.go b/app/slashcommands/helper_test.go
index 57faf1c805..8c3ff4e257 100644
--- a/app/slashcommands/helper_test.go
+++ b/app/slashcommands/helper_test.go
@@ -21,7 +21,6 @@ import (
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
"github.com/mattermost/mattermost-server/v6/store/localcachelayer"
- "github.com/mattermost/mattermost-server/v6/utils"
)
type TestHelper struct {
@@ -36,6 +35,7 @@ type TestHelper struct {
SystemAdminUser *model.User
LogBuffer *bytes.Buffer
+ TestLogger *mlog.Logger
IncludeCacheLayer bool
tempWorkspace string
@@ -49,15 +49,15 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
memoryStore := config.NewTestMemoryStore()
- config := memoryStore.Get()
+ memoryConfig := memoryStore.Get()
if configSet != nil {
- configSet(config)
+ configSet(memoryConfig)
}
- *config.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
- *config.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
- *config.PluginSettings.AutomaticPrepackagedPlugins = false
- *config.LogSettings.EnableSentry = false // disable error reporting during tests
- memoryStore.Set(config)
+ *memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins")
+ *memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp")
+ *memoryConfig.PluginSettings.AutomaticPrepackagedPlugins = false
+ *memoryConfig.LogSettings.EnableSentry = false // disable error reporting during tests
+ memoryStore.Set(memoryConfig)
buffer := &bytes.Buffer{}
@@ -74,7 +74,15 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
} else {
options = append(options, app.StoreOverride(dbStore))
}
- options = append(options, app.SetLogger(mlog.NewTestingLogger(tb, buffer)))
+
+ testLogger, _ := mlog.NewLogger()
+ logCfg, _ := config.MloggerConfigFromLoggerConfig(&memoryConfig.LogSettings, nil, config.GetLogFileLocation)
+ if errCfg := testLogger.ConfigureTargets(logCfg); errCfg != nil {
+ panic("failed to configure test logger: " + errCfg.Error())
+ }
+ // lock logger config so server init cannot override it during testing.
+ testLogger.LockConfiguration()
+ options = append(options, app.SetLogger(testLogger))
s, err := app.NewServer(options...)
if err != nil {
@@ -86,6 +94,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
Context: &request.Context{},
Server: s,
LogBuffer: buffer,
+ TestLogger: testLogger,
IncludeCacheLayer: includeCacheLayer,
}
@@ -188,12 +197,11 @@ func (th *TestHelper) createTeam() *model.Team {
Type: model.TeamOpen,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if team, err = th.App.CreateTeam(th.Context, team); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
+
return team
}
@@ -216,7 +224,6 @@ func (th *TestHelper) createUserOrGuest(guest bool) *model.User {
EmailVerified: true,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if guest {
if user, err = th.App.CreateGuest(th.Context, user); err != nil {
@@ -227,7 +234,6 @@ func (th *TestHelper) createUserOrGuest(guest bool) *model.User {
panic(err)
}
}
- utils.EnableDebugLogForTest()
return user
}
@@ -262,7 +268,6 @@ func (th *TestHelper) createChannel(team *model.Team, channelType model.ChannelT
option(channel)
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if channel, err = th.App.CreateChannel(th.Context, channel, true); err != nil {
panic(err)
@@ -284,7 +289,6 @@ func (th *TestHelper) createChannel(team *model.Team, channelType model.ChannelT
panic(err)
}
}
- utils.EnableDebugLogForTest()
return channel
}
@@ -299,34 +303,28 @@ func (th *TestHelper) createChannelWithAnotherUser(team *model.Team, channelType
CreatorId: userID,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if channel, err = th.App.CreateChannel(th.Context, channel, true); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
func (th *TestHelper) createDmChannel(user *model.User) *model.Channel {
- utils.DisableDebugLogForTest()
var err *model.AppError
var channel *model.Channel
if channel, err = th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, user.Id); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
func (th *TestHelper) createGroupChannel(user1 *model.User, user2 *model.User) *model.Channel {
- utils.DisableDebugLogForTest()
var err *model.AppError
var channel *model.Channel
if channel, err = th.App.CreateGroupChannel([]string{th.BasicUser.Id, user1.Id, user2.Id}, th.BasicUser.Id); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
@@ -340,36 +338,25 @@ func (th *TestHelper) createPost(channel *model.Channel) *model.Post {
CreateAt: model.GetMillis() - 10000,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if post, err = th.App.CreatePost(th.Context, post, channel, false, true); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return post
}
func (th *TestHelper) linkUserToTeam(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
_, err := th.App.JoinUserToTeam(th.Context, team, user, "")
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) addUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember {
- utils.DisableDebugLogForTest()
-
member, err := th.App.AddUserToChannel(user, channel, false)
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
-
return member
}
@@ -401,11 +388,8 @@ func (th *TestHelper) tearDown() {
}
func (th *TestHelper) removePermissionFromRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
@@ -417,7 +401,6 @@ func (th *TestHelper) removePermissionFromRole(permission string, roleName strin
}
if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
- utils.EnableDebugLogForTest()
return
}
@@ -425,25 +408,18 @@ func (th *TestHelper) removePermissionFromRole(permission string, roleName strin
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) addPermissionToRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
for _, existingPermission := range role.Permissions {
if existingPermission == permission {
- utils.EnableDebugLogForTest()
return
}
}
@@ -452,9 +428,6 @@ func (th *TestHelper) addPermissionToRole(permission string, roleName string) {
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
diff --git a/app/slashcommands/main_test.go b/app/slashcommands/main_test.go
index 97029616bf..dd2d0d52f0 100644
--- a/app/slashcommands/main_test.go
+++ b/app/slashcommands/main_test.go
@@ -6,7 +6,6 @@ package slashcommands
import (
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -18,8 +17,6 @@ func TestMain(m *testing.M) {
EnableResources: true,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/audit/audit.go b/audit/audit.go
index c63935f6f3..d0974fb4bf 100644
--- a/audit/audit.go
+++ b/audit/audit.go
@@ -5,17 +5,12 @@ package audit
import (
"fmt"
- "sort"
-
- "github.com/mattermost/logr"
- "github.com/mattermost/logr/format"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
type Audit struct {
- lgr *logr.Logr
- logger logr.Logger
+ logger *mlog.Logger
// OnQueueFull is called on an attempt to add an audit record to a full queue.
// Return true to drop record, or false to block until there is room in queue.
@@ -26,56 +21,34 @@ type Audit struct {
}
func (a *Audit) Init(maxQueueSize int) {
- a.lgr = &logr.Logr{MaxQueueSize: maxQueueSize}
- a.logger = a.lgr.NewLogger()
-
- a.lgr.OnQueueFull = a.onQueueFull
- a.lgr.OnTargetQueueFull = a.onTargetQueueFull
- a.lgr.OnLoggerError = a.onLoggerError
-}
-
-// MakeFilter creates a filter which only allows the specified audit levels to be output.
-func (a *Audit) MakeFilter(level ...mlog.LogLevel) *logr.CustomFilter {
- filter := &logr.CustomFilter{}
- for _, l := range level {
- filter.Add(logr.Level(l))
- }
- return filter
-}
-
-// MakeJSONFormatter creates a formatter that outputs JSON suitable for audit records.
-func (a *Audit) MakeJSONFormatter() *format.JSON {
- f := &format.JSON{
- DisableTimestamp: true,
- DisableMsg: true,
- DisableStacktrace: true,
- DisableLevel: true,
- ContextSorter: sortAuditFields,
- }
- return f
+ a.logger, _ = mlog.NewLogger(
+ mlog.MaxQueueSize(maxQueueSize),
+ mlog.OnLoggerError(a.onLoggerError),
+ mlog.OnQueueFull(a.onQueueFull),
+ mlog.OnTargetQueueFull(a.onTargetQueueFull),
+ )
}
// LogRecord emits an audit record with complete info.
-func (a *Audit) LogRecord(level mlog.LogLevel, rec Record) {
- flds := logr.Fields{}
- flds[KeyAPIPath] = rec.APIPath
- flds[KeyEvent] = rec.Event
- flds[KeyStatus] = rec.Status
- flds[KeyUserID] = rec.UserID
- flds[KeySessionID] = rec.SessionID
- flds[KeyClient] = rec.Client
- flds[KeyIPAddress] = rec.IPAddress
-
- for k, v := range rec.Meta {
- flds[k] = v
+func (a *Audit) LogRecord(level mlog.Level, rec Record) {
+ flds := []mlog.Field{
+ mlog.String(KeyAPIPath, rec.APIPath),
+ mlog.String(KeyEvent, rec.Event),
+ mlog.String(KeyStatus, rec.Status),
+ mlog.String(KeyUserID, rec.UserID),
+ mlog.String(KeySessionID, rec.SessionID),
+ mlog.String(KeyClient, rec.Client),
+ mlog.String(KeyIPAddress, rec.IPAddress),
}
- l := a.logger.WithFields(flds)
- l.Log(logr.Level(level))
+ for k, v := range rec.Meta {
+ flds = append(flds, mlog.Any(k, v))
+ }
+ a.logger.Log(level, "", flds...)
}
// Log emits an audit record based on minimum required info.
-func (a *Audit) Log(level mlog.LogLevel, path string, evt string, status string, userID string, sessionID string, meta Meta) {
+func (a *Audit) Log(level mlog.Level, path string, evt string, status string, userID string, sessionID string, meta Meta) {
a.LogRecord(level, Record{
APIPath: path,
Event: evt,
@@ -86,20 +59,30 @@ func (a *Audit) Log(level mlog.LogLevel, path string, evt string, status string,
})
}
-// AddTarget adds a Logr target to the list of targets each audit record will be output to.
-func (a *Audit) AddTarget(target logr.Target) {
- a.lgr.AddTarget(target)
+// Configure sets zero or more target to output audit logs to.
+func (a *Audit) Configure(cfg mlog.LoggerConfiguration) error {
+ return a.logger.ConfigureTargets(cfg)
}
-// Shutdown cleanly stops the audit engine after making best efforts to flush all targets.
-func (a *Audit) Shutdown() {
- err := a.lgr.Shutdown()
+// Flush attempts to write all queued audit records to all targets.
+func (a *Audit) Flush() error {
+ err := a.logger.Flush()
if err != nil {
a.onLoggerError(err)
}
+ return err
}
-func (a *Audit) onQueueFull(rec *logr.LogRec, maxQueueSize int) bool {
+// Shutdown cleanly stops the audit engine after making best efforts to flush all targets.
+func (a *Audit) Shutdown() error {
+ err := a.logger.Shutdown()
+ if err != nil {
+ a.onLoggerError(err)
+ }
+ return err
+}
+
+func (a *Audit) onQueueFull(rec *mlog.LogRec, maxQueueSize int) bool {
if a.OnQueueFull != nil {
return a.OnQueueFull("main", maxQueueSize)
}
@@ -107,7 +90,7 @@ func (a *Audit) onQueueFull(rec *logr.LogRec, maxQueueSize int) bool {
return true
}
-func (a *Audit) onTargetQueueFull(target logr.Target, rec *logr.LogRec, maxQueueSize int) bool {
+func (a *Audit) onTargetQueueFull(target mlog.Target, rec *mlog.LogRec, maxQueueSize int) bool {
if a.OnQueueFull != nil {
return a.OnQueueFull(fmt.Sprintf("%v", target), maxQueueSize)
}
@@ -118,58 +101,7 @@ func (a *Audit) onTargetQueueFull(target logr.Target, rec *logr.LogRec, maxQueue
func (a *Audit) onLoggerError(err error) {
if a.OnError != nil {
a.OnError(err)
+ return
}
-}
-
-// sortAuditFields sorts the context fields of an audit record such that some fields
-// are prepended in order, some are appended in order, and the rest are sorted alphabetically.
-// This is done to make reading the records easier since common fields will appear in the same order.
-func sortAuditFields(fields logr.Fields) []format.ContextField {
- prependKeys := []string{KeyEvent, KeyStatus, KeyUserID, KeySessionID, KeyIPAddress}
- appendKeys := []string{KeyClusterID, KeyClient}
-
- // sort alphabetically any fields not in the prepend/append lists.
- keys := make([]string, 0, len(fields))
- for k := range fields {
- if !findIn(k, prependKeys, appendKeys) {
- keys = append(keys, k)
- }
- }
- sort.Strings(keys)
-
- allKeys := make([]string, 0, len(fields))
-
- // add any prepends that exist in fields
- for _, k := range prependKeys {
- if _, ok := fields[k]; ok {
- allKeys = append(allKeys, k)
- }
- }
-
- // sorted
- allKeys = append(allKeys, keys...)
-
- // add any appends that exist in fields
- for _, k := range appendKeys {
- if _, ok := fields[k]; ok {
- allKeys = append(allKeys, k)
- }
- }
-
- cfs := make([]format.ContextField, 0, len(allKeys))
- for _, k := range allKeys {
- cfs = append(cfs, format.ContextField{Key: k, Val: fields[k]})
- }
- return cfs
-}
-
-func findIn(s string, arrs ...[]string) bool {
- for _, list := range arrs {
- for _, key := range list {
- if s == key {
- return true
- }
- }
- }
- return false
+ mlog.Error("Auditing error", mlog.Err(err))
}
diff --git a/audit/audit_test.go b/audit/audit_test.go
deleted file mode 100644
index 7900c78646..0000000000
--- a/audit/audit_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package audit
-
-import (
- "testing"
-
- "github.com/mattermost/logr"
- "github.com/mattermost/logr/format"
- "github.com/stretchr/testify/require"
-)
-
-func Test_sortAuditFields(t *testing.T) {
- type args struct {
- fields logr.Fields
- }
- tests := []struct {
- name string
- args args
- want []format.ContextField
- }{
- {name: "empty list",
- args: args{fields: logr.Fields{}},
- want: []format.ContextField{},
- },
- {name: "partial list",
- args: args{fields: logr.Fields{"zProp": "x", "xProp": "x", "yProp": "x", KeyClusterID: "x", KeyEvent: "x"}},
- want: []format.ContextField{
- {Key: KeyEvent, Val: "x"},
- {Key: "xProp", Val: "x"},
- {Key: "yProp", Val: "x"},
- {Key: "zProp", Val: "x"},
- {Key: KeyClusterID, Val: "x"},
- },
- },
- {name: "append/prepend only list",
- args: args{fields: logr.Fields{KeyClusterID: "x", KeyEvent: "x", KeySessionID: "x", KeyIPAddress: "x", KeyClient: "x",
- KeyUserID: "x", KeyStatus: "x"}},
- want: []format.ContextField{
- // prepend: KeyEvent, KeyStatus, KeyUserID, KeySessionID, KeyIPAddress
- // append: KeyClusterID, KeyClient
- {Key: KeyEvent, Val: "x"},
- {Key: KeyStatus, Val: "x"},
- {Key: KeyUserID, Val: "x"},
- {Key: KeySessionID, Val: "x"},
- {Key: KeyIPAddress, Val: "x"},
- {Key: KeyClusterID, Val: "x"},
- {Key: KeyClient, Val: "x"},
- },
- },
- {name: "sortables only list",
- args: args{fields: logr.Fields{"zProp": "x", "xProp": "x", "yProp": "x"}},
- want: []format.ContextField{
- {Key: "xProp", Val: "x"},
- {Key: "yProp", Val: "x"},
- {Key: "zProp", Val: "x"},
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got := sortAuditFields(tt.args.fields)
- require.Equal(t, tt.want, got)
- })
- }
-}
diff --git a/audit/file.go b/audit/file.go
deleted file mode 100644
index 2d47b4c692..0000000000
--- a/audit/file.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package audit
-
-import (
- "os"
-
- "github.com/mattermost/logr"
- "github.com/mattermost/logr/target"
-)
-
-type FileOptions target.FileOptions
-
-// NewFileTarget creates a target capable of outputting log records to a rotated file.
-func NewFileTarget(filter logr.Filter, formatter logr.Formatter, opts FileOptions, maxQSize int) (*target.File, error) {
- fopts := target.FileOptions(opts)
- err := checkFileWritable(fopts.Filename)
- if err != nil {
- return nil, err
- }
- target := target.NewFileTarget(filter, formatter, fopts, maxQSize)
- return target, nil
-}
-
-func checkFileWritable(filename string) error {
- // try opening/creating the file for writing
- file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600)
- if err != nil {
- return err
- }
- file.Close()
- return nil
-}
diff --git a/cmd/mattermost/commands/logs.go b/cmd/mattermost/commands/logs.go
deleted file mode 100644
index bab0a12e6b..0000000000
--- a/cmd/mattermost/commands/logs.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package commands
-
-import (
- "io"
- "os"
-
- "github.com/spf13/cobra"
-
- "github.com/mattermost/mattermost-server/v6/shared/mlog/human"
-)
-
-var LogsCmd = &cobra.Command{
- Use: "logs",
- Short: "Display logs in a human-readable format",
- RunE: logsCmdF,
-}
-
-func init() {
- LogsCmd.Flags().Bool("logrus", false, "Use logrus for formatting.")
- RootCmd.AddCommand(LogsCmd)
-}
-
-func logsCmdF(command *cobra.Command, args []string) error {
- // check stdin to see if we have a pipe
- fi, err := os.Stdin.Stat()
- if err != nil {
- return err
- }
-
- var input io.Reader
- if fi.Size() == 0 && fi.Mode()&os.ModeNamedPipe == 0 {
- file, err := os.Open("mattermost.log")
- if err != nil {
- return err
- }
- defer file.Close()
- input = file
- } else {
- input = os.Stdin
- }
- var writer human.LogWriter
-
- if flag, _ := command.Flags().GetBool("logrus"); flag {
- writer = human.NewLogrusWriter(os.Stdout)
- } else {
- writer = human.NewSimpleWriter(os.Stdout)
- }
- human.ProcessLogs(input, writer)
-
- return nil
-}
diff --git a/cmd/mattermost/commands/main_test.go b/cmd/mattermost/commands/main_test.go
index 0905703763..035c15b2b1 100644
--- a/cmd/mattermost/commands/main_test.go
+++ b/cmd/mattermost/commands/main_test.go
@@ -9,7 +9,6 @@ import (
"testing"
"github.com/mattermost/mattermost-server/v6/api4"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -28,8 +27,6 @@ func TestMain(m *testing.M) {
EnableResources: true,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
api4.SetMainHelper(mainHelper)
diff --git a/config/emitter.go b/config/emitter.go
index 9074868879..4431cba2dc 100644
--- a/config/emitter.go
+++ b/config/emitter.go
@@ -57,7 +57,7 @@ func (e *logSrcEmitter) RemoveListener(id string) {
}
// invokeConfigListeners synchronously notifies all listeners about the configuration change.
-func (e *logSrcEmitter) invokeConfigListeners(oldCfg, newCfg mlog.LogTargetCfg) {
+func (e *logSrcEmitter) invokeConfigListeners(oldCfg, newCfg mlog.LoggerConfiguration) {
e.listeners.Range(func(key, value interface{}) bool {
listener := value.(LogSrcListener)
listener(oldCfg, newCfg)
diff --git a/config/emitter_test.go b/config/emitter_test.go
index 9906e851d3..364b7b2944 100644
--- a/config/emitter_test.go
+++ b/config/emitter_test.go
@@ -56,18 +56,18 @@ func TestEmitter(t *testing.T) {
func TestLogSrcEmitter(t *testing.T) {
var e logSrcEmitter
- expectedOldCfg := make(mlog.LogTargetCfg)
- expectedNewCfg := make(mlog.LogTargetCfg)
+ expectedOldCfg := make(mlog.LoggerConfiguration)
+ expectedNewCfg := make(mlog.LoggerConfiguration)
listener1 := false
- id1 := e.AddListener(func(oldCfg, newCfg mlog.LogTargetCfg) {
+ id1 := e.AddListener(func(oldCfg, newCfg mlog.LoggerConfiguration) {
assert.Equal(t, expectedOldCfg, oldCfg)
assert.Equal(t, expectedNewCfg, newCfg)
listener1 = true
})
listener2 := false
- id2 := e.AddListener(func(oldCfg, newCfg mlog.LogTargetCfg) {
+ id2 := e.AddListener(func(oldCfg, newCfg mlog.LoggerConfiguration) {
assert.Equal(t, expectedOldCfg, oldCfg)
assert.Equal(t, expectedNewCfg, newCfg)
listener2 = true
diff --git a/config/logging.go b/config/logconfigsrc.go
similarity index 74%
rename from config/logging.go
rename to config/logconfigsrc.go
index 9e33daacc0..fa082caaf0 100644
--- a/config/logging.go
+++ b/config/logconfigsrc.go
@@ -6,7 +6,6 @@ package config
import (
"encoding/json"
"errors"
- "os"
"path/filepath"
"strings"
"sync"
@@ -14,23 +13,17 @@ import (
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
-type LogSrcListener func(old, new mlog.LogTargetCfg)
+type LogSrcListener func(old, new mlog.LoggerConfiguration)
// LogConfigSrc abstracts the Advanced Logging configuration so that implementations can
// fetch from file, database, etc.
type LogConfigSrc interface {
// Get fetches the current, cached configuration.
- Get() mlog.LogTargetCfg
+ Get() mlog.LoggerConfiguration
// Set updates the dsn specifying the source and reloads
Set(dsn string, configStore *Store) (err error)
- // AddListener adds a callback function to invoke when the configuration is modified.
- AddListener(listener LogSrcListener) string
-
- // RemoveListener removes a callback function using an id returned from AddListener.
- RemoveListener(id string)
-
// Close cleans up resources.
Close() error
}
@@ -38,6 +31,10 @@ type LogConfigSrc interface {
// NewLogConfigSrc creates an advanced logging configuration source, backed by a
// file, JSON string, or database.
func NewLogConfigSrc(dsn string, configStore *Store) (LogConfigSrc, error) {
+ if dsn == "" {
+ return nil, errors.New("dsn should not be empty")
+ }
+
if configStore == nil {
return nil, errors.New("configStore should not be nil")
}
@@ -63,7 +60,7 @@ func NewLogConfigSrc(dsn string, configStore *Store) (LogConfigSrc, error) {
type jsonSrc struct {
logSrcEmitter
mutex sync.RWMutex
- cfg mlog.LogTargetCfg
+ cfg mlog.LoggerConfiguration
}
func newJSONSrc(data string) (*jsonSrc, error) {
@@ -72,7 +69,7 @@ func newJSONSrc(data string) (*jsonSrc, error) {
}
// Get fetches the current, cached configuration
-func (src *jsonSrc) Get() mlog.LogTargetCfg {
+func (src *jsonSrc) Get() mlog.LoggerConfiguration {
src.mutex.RLock()
defer src.mutex.RUnlock()
return src.cfg
@@ -89,7 +86,7 @@ func (src *jsonSrc) Set(data string, _ *Store) error {
return nil
}
-func (src *jsonSrc) set(cfg mlog.LogTargetCfg) {
+func (src *jsonSrc) set(cfg mlog.LoggerConfiguration) {
src.mutex.Lock()
defer src.mutex.Unlock()
@@ -106,11 +103,9 @@ func (src *jsonSrc) Close() error {
// fileSrc
type fileSrc struct {
- logSrcEmitter
mutex sync.RWMutex
- cfg mlog.LogTargetCfg
-
- path string
+ cfg mlog.LoggerConfiguration
+ path string
}
func newFileSrc(path string, configStore *Store) (*fileSrc, error) {
@@ -124,7 +119,7 @@ func newFileSrc(path string, configStore *Store) (*fileSrc, error) {
}
// Get fetches the current, cached configuration
-func (src *fileSrc) Get() mlog.LogTargetCfg {
+func (src *fileSrc) Get() mlog.LoggerConfiguration {
src.mutex.RLock()
defer src.mutex.RUnlock()
return src.cfg
@@ -145,26 +140,14 @@ func (src *fileSrc) Set(path string, configStore *Store) error {
}
src.set(cfg)
-
- // If path is a real file and not just the name of a database resource then watch it for changes.
- // Absolute paths are explicit and require no resolution.
- if _, err = os.Stat(path); os.IsNotExist(err) {
- return nil
- }
-
- src.mutex.Lock()
- defer src.mutex.Unlock()
-
return nil
}
-func (src *fileSrc) set(cfg mlog.LogTargetCfg) {
+func (src *fileSrc) set(cfg mlog.LoggerConfiguration) {
src.mutex.Lock()
defer src.mutex.Unlock()
- old := src.cfg
src.cfg = cfg
- src.invokeConfigListeners(old, cfg)
}
// Close cleans up resources.
@@ -172,8 +155,8 @@ func (src *fileSrc) Close() error {
return nil
}
-func logTargetCfgFromJSON(data []byte) (mlog.LogTargetCfg, error) {
- cfg := make(mlog.LogTargetCfg)
+func logTargetCfgFromJSON(data []byte) (mlog.LoggerConfiguration, error) {
+ cfg := make(mlog.LoggerConfiguration)
err := json.Unmarshal(data, &cfg)
if err != nil {
return nil, err
diff --git a/config/logging_test.go b/config/logconfigsrc_test.go
similarity index 100%
rename from config/logging_test.go
rename to config/logconfigsrc_test.go
diff --git a/config/logger.go b/config/logger.go
new file mode 100644
index 0000000000..23c777d21b
--- /dev/null
+++ b/config/logger.go
@@ -0,0 +1,216 @@
+// 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/v6/model"
+ "github.com/mattermost/mattermost-server/v6/shared/mlog"
+ "github.com/mattermost/mattermost-server/v6/utils/fileutils"
+)
+
+const (
+ LogRotateSize = 10000
+ LogCompress = true
+ LogRotateMaxAge = 0
+ LogRotateMaxBackups = 0
+ LogFilename = "mattermost.log"
+ LogNotificationFilename = "notifications.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": true, "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 GetNotificationsLogFileLocation(fileLocation string) string {
+ if fileLocation == "" {
+ fileLocation, _ = fileutils.FindDir("logs")
+ }
+
+ return filepath.Join(fileLocation, LogNotificationFilename)
+}
+
+func GetLogSettingsFromNotificationsLogSettings(notificationLogSettings *model.NotificationLogSettings) *model.LogSettings {
+ settings := &model.LogSettings{}
+ settings.SetDefaults()
+ settings.ConsoleJson = notificationLogSettings.ConsoleJson
+ settings.ConsoleLevel = notificationLogSettings.ConsoleLevel
+ settings.EnableConsole = notificationLogSettings.EnableConsole
+ settings.EnableFile = notificationLogSettings.EnableFile
+ settings.FileJson = notificationLogSettings.FileJson
+ settings.FileLevel = notificationLogSettings.FileLevel
+ settings.FileLocation = notificationLogSettings.FileLocation
+ settings.AdvancedLoggingConfig = notificationLogSettings.AdvancedLoggingConfig
+ settings.EnableColor = notificationLogSettings.EnableColor
+ return settings
+}
+
+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
+ }
+
+ target := mlog.TargetCfg{
+ Type: "file",
+ Levels: levels,
+ Options: makeFileOptions(filename),
+ 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 {
+ str := fmt.Sprintf(`{"filename": "%s", "max_size": %d, "max_age": %d, "max_backups": %d, "compress": %t}`,
+ filename, LogRotateSize, LogRotateMaxAge, LogRotateMaxBackups, LogCompress)
+ return json.RawMessage(str)
+}
diff --git a/config/main_test.go b/config/main_test.go
index 58e913108c..36c7f2e36f 100644
--- a/config/main_test.go
+++ b/config/main_test.go
@@ -12,7 +12,6 @@ import (
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/model"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -23,8 +22,6 @@ func TestMain(m *testing.M) {
EnableStore: true,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/einterfaces/metrics.go b/einterfaces/metrics.go
index 4815a35b01..56e6cb5aa0 100644
--- a/einterfaces/metrics.go
+++ b/einterfaces/metrics.go
@@ -4,8 +4,8 @@
package einterfaces
import (
- "github.com/mattermost/logr"
"github.com/mattermost/mattermost-server/v6/model"
+ "github.com/mattermost/mattermost-server/v6/shared/mlog"
)
type MetricsInterface interface {
@@ -66,7 +66,7 @@ type MetricsInterface interface {
ObservePluginAPIDuration(pluginID, apiName string, success bool, elapsed float64)
ObserveEnabledUsers(users int64)
- GetLoggerMetricsCollector() logr.MetricsCollector
+ GetLoggerMetricsCollector() mlog.MetricsCollector
IncrementRemoteClusterMsgSentCounter(remoteID string)
IncrementRemoteClusterMsgReceivedCounter(remoteID string)
diff --git a/einterfaces/mocks/MetricsInterface.go b/einterfaces/mocks/MetricsInterface.go
index b854a567b2..db733f8b8f 100644
--- a/einterfaces/mocks/MetricsInterface.go
+++ b/einterfaces/mocks/MetricsInterface.go
@@ -5,7 +5,7 @@
package mocks
import (
- logr "github.com/mattermost/logr"
+ logr "github.com/mattermost/logr/v2"
mock "github.com/stretchr/testify/mock"
model "github.com/mattermost/mattermost-server/v6/model"
diff --git a/go.mod b/go.mod
index 04111ac781..9ef0fafdb4 100644
--- a/go.mod
+++ b/go.mod
@@ -50,7 +50,7 @@ require (
github.com/hashicorp/go-hclog v0.16.1
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
github.com/hashicorp/go-msgpack v1.1.5 // indirect
- github.com/hashicorp/go-multierror v1.1.1
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.4.2
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
@@ -72,7 +72,8 @@ require (
github.com/mattermost/gosaml2 v0.3.3
github.com/mattermost/gziphandler v0.0.1
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d
- github.com/mattermost/logr v1.0.13
+ github.com/mattermost/logr v1.0.13 // indirect
+ github.com/mattermost/logr/v2 v2.0.10
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
@@ -102,7 +103,7 @@ require (
github.com/russellhaering/goxmldsig v1.1.0
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 // indirect
- github.com/sirupsen/logrus v1.8.1
+ github.com/sirupsen/logrus v1.8.1 // indirect
github.com/smartystreets/assertions v1.0.0 // indirect
github.com/spf13/cobra v1.1.3
github.com/splitio/go-client/v6 v6.1.0
@@ -118,7 +119,7 @@ require (
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.4
github.com/wiggin77/merror v1.0.3
- github.com/wiggin77/srslog v1.0.1
+ github.com/wiggin77/srslog v1.0.1 // indirect
github.com/willf/bitset v1.1.11 // indirect
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c
github.com/yuin/goldmark v1.3.8
@@ -126,7 +127,7 @@ require (
go.opentelemetry.io/otel/internal/metric v0.21.0 // indirect
go.uber.org/atomic v1.8.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
- go.uber.org/zap v1.17.0
+ go.uber.org/zap v1.17.0 // indirect
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
@@ -138,7 +139,7 @@ require (
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/mail.v2 v2.3.1
- gopkg.in/natefinch/lumberjack.v2 v2.0.0
+ gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/olivere/elastic.v6 v6.2.35
gopkg.in/yaml.v2 v2.4.0
willnorris.com/go/imageproxy v0.10.0
diff --git a/go.sum b/go.sum
index 9e7ed86417..bd6ae9c061 100644
--- a/go.sum
+++ b/go.sum
@@ -655,6 +655,20 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ=
github.com/mattermost/logr v1.0.13 h1:6F/fM3csvH6Oy5sUpJuW7YyZSzZZAhJm5VcgKMxA2P8=
github.com/mattermost/logr v1.0.13/go.mod h1:Mt4DPu1NXMe6JxPdwCC0XBoxXmN9eXOIRPoZarU2PXs=
+github.com/mattermost/logr/v2 v2.0.4 h1:LiqvzNNfia23hlu1zmmCDmjqmSfwWNsEtFlL4/7jf8o=
+github.com/mattermost/logr/v2 v2.0.4/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
+github.com/mattermost/logr/v2 v2.0.5 h1:qYuPn0FSDtsmxcwhGUsSDkiWCH17ZYts6BLAAgsp1ks=
+github.com/mattermost/logr/v2 v2.0.5/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
+github.com/mattermost/logr/v2 v2.0.6 h1:Ewmtqm+o6y6yDSqdMZdrP5o0P7rCKbBNJQl+FbhcWHg=
+github.com/mattermost/logr/v2 v2.0.6/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
+github.com/mattermost/logr/v2 v2.0.7 h1:rcwGa3faMWa/0k841FZhrcb8qZexfV8sk9ZVCV/8KUg=
+github.com/mattermost/logr/v2 v2.0.7/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
+github.com/mattermost/logr/v2 v2.0.8 h1:HQuie671ZtmIp0Y6gY0u34UQvnBw8rPFLeLxWOxv5VM=
+github.com/mattermost/logr/v2 v2.0.8/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
+github.com/mattermost/logr/v2 v2.0.9 h1:WZev0JYaWmRa/wmpXe8xGA+YDTj9iqbn25rM55Hgutw=
+github.com/mattermost/logr/v2 v2.0.9/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
+github.com/mattermost/logr/v2 v2.0.10 h1:i6rJbuX/EkBM9maM8M0eJ3rxB+fsBKNslPvzSlA2w/M=
+github.com/mattermost/logr/v2 v2.0.10/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 h1:G9tL6JXRBMzjuD1kkBtcnd42kUiT6QDwxfFYu7adM6o=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
diff --git a/migrations/helper_test.go b/migrations/helper_test.go
index 23a278cd31..cfc7d08e57 100644
--- a/migrations/helper_test.go
+++ b/migrations/helper_test.go
@@ -5,13 +5,14 @@ package migrations
import (
"os"
+ "testing"
"github.com/mattermost/mattermost-server/v6/app"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/config"
"github.com/mattermost/mattermost-server/v6/model"
+ "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store/localcachelayer"
- "github.com/mattermost/mattermost-server/v6/utils"
)
type TestHelper struct {
@@ -27,6 +28,8 @@ type TestHelper struct {
SystemAdminUser *model.User
tempWorkspace string
+
+ TestLogger *mlog.Logger
}
func setupTestHelper(enterprise bool) *TestHelper {
@@ -44,6 +47,15 @@ func setupTestHelper(enterprise bool) *TestHelper {
options = append(options, app.StoreOverride(mainHelper.Store))
options = append(options, app.SkipPostInitializiation())
+ testLogger, _ := mlog.NewLogger()
+ logCfg, _ := config.MloggerConfigFromLoggerConfig(&newConfig.LogSettings, nil, config.GetLogFileLocation)
+ if errCfg := testLogger.ConfigureTargets(logCfg); errCfg != nil {
+ panic("failed to configure test logger: " + errCfg.Error())
+ }
+ // lock logger config so server init cannot override it during testing.
+ testLogger.LockConfiguration()
+ options = append(options, app.SetLogger(testLogger))
+
s, err := app.NewServer(options...)
if err != nil {
panic(err)
@@ -55,9 +67,10 @@ func setupTestHelper(enterprise bool) *TestHelper {
}
th := &TestHelper{
- App: app.New(app.ServerConnector(s)),
- Context: &request.Context{},
- Server: s,
+ App: app.New(app.ServerConnector(s)),
+ Context: &request.Context{},
+ Server: s,
+ TestLogger: testLogger,
}
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 50 })
@@ -89,11 +102,11 @@ func setupTestHelper(enterprise bool) *TestHelper {
return th
}
-func SetupEnterprise() *TestHelper {
+func SetupEnterprise(tb testing.TB) *TestHelper {
return setupTestHelper(true)
}
-func Setup() *TestHelper {
+func Setup(tb testing.TB) *TestHelper {
return setupTestHelper(false)
}
@@ -126,12 +139,10 @@ func (th *TestHelper) CreateTeam() *model.Team {
Type: model.TeamOpen,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if team, err = th.App.CreateTeam(th.Context, team); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return team
}
@@ -146,12 +157,10 @@ func (th *TestHelper) CreateUser() *model.User {
EmailVerified: true,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if user, err = th.App.CreateUser(th.Context, user); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return user
}
@@ -170,23 +179,19 @@ func (th *TestHelper) createChannel(team *model.Team, channelType model.ChannelT
CreatorId: th.BasicUser.Id,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if channel, err = th.App.CreateChannel(th.Context, channel, true); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
func (th *TestHelper) CreateDmChannel(user *model.User) *model.Channel {
- utils.DisableDebugLogForTest()
var err *model.AppError
var channel *model.Channel
if channel, err = th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, user.Id); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return channel
}
@@ -200,36 +205,25 @@ func (th *TestHelper) CreatePost(channel *model.Channel) *model.Post {
CreateAt: model.GetMillis() - 10000,
}
- utils.DisableDebugLogForTest()
var err *model.AppError
if post, err = th.App.CreatePost(th.Context, post, channel, false, true); err != nil {
panic(err)
}
- utils.EnableDebugLogForTest()
return post
}
func (th *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) {
- utils.DisableDebugLogForTest()
-
_, err := th.App.JoinUserToTeam(th.Context, team, user, "")
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
}
func (th *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember {
- utils.DisableDebugLogForTest()
-
member, err := th.App.AddUserToChannel(user, channel, false)
if err != nil {
panic(err)
}
-
- utils.EnableDebugLogForTest()
-
return member
}
diff --git a/migrations/main_test.go b/migrations/main_test.go
index 8826e085b5..372655a617 100644
--- a/migrations/main_test.go
+++ b/migrations/main_test.go
@@ -6,7 +6,6 @@ package migrations
import (
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -18,8 +17,6 @@ func TestMain(m *testing.M) {
EnableResources: true,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/migrations/migrations_test.go b/migrations/migrations_test.go
index d88b63ade5..5adebfcdad 100644
--- a/migrations/migrations_test.go
+++ b/migrations/migrations_test.go
@@ -16,7 +16,7 @@ func TestGetMigrationState(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
- th := Setup()
+ th := Setup(t)
defer th.TearDown()
migrationKey := model.NewId()
diff --git a/model/config.go b/model/config.go
index 5721bc1b92..82c6d6e433 100644
--- a/model/config.go
+++ b/model/config.go
@@ -1223,6 +1223,12 @@ type LogSettings struct {
AdvancedLoggingConfig *string `access:"environment_logging,write_restrictable,cloud_restrictable"`
}
+func NewLogSettings() *LogSettings {
+ settings := &LogSettings{}
+ settings.SetDefaults()
+ return settings
+}
+
func (s *LogSettings) SetDefaults() {
if s.EnableConsole == nil {
s.EnableConsole = NewBool(true)
diff --git a/plugin/hclog_adapter.go b/plugin/hclog_adapter.go
index d4e07d14df..4142298f48 100644
--- a/plugin/hclog_adapter.go
+++ b/plugin/hclog_adapter.go
@@ -115,7 +115,7 @@ func (h *hclogAdapter) ResetNamed(name string) hclog.Logger {
}
func (h *hclogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
- return h.wrappedLogger.StdLog()
+ return h.wrappedLogger.StdLogger(mlog.LvlInfo)
}
func (h *hclogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
diff --git a/plugin/health_check_test.go b/plugin/health_check_test.go
index 12f8d95389..1854af0a9e 100644
--- a/plugin/health_check_test.go
+++ b/plugin/health_check_test.go
@@ -52,12 +52,8 @@ func testPluginHealthCheckSuccess(t *testing.T) {
require.NoError(t, err)
bundle := model.BundleInfoForPath(dir)
- log := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- })
+ log := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
+ defer log.Shutdown()
supervisor, err := newSupervisor(bundle, nil, nil, log, nil)
require.NoError(t, err)
@@ -99,12 +95,8 @@ func testPluginHealthCheckPanic(t *testing.T) {
require.NoError(t, err)
bundle := model.BundleInfoForPath(dir)
- log := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- })
+ log := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
+ defer log.Shutdown()
supervisor, err := newSupervisor(bundle, nil, nil, log, nil)
require.NoError(t, err)
diff --git a/plugin/supervisor.go b/plugin/supervisor.go
index 883321fbcc..49dc70bc54 100644
--- a/plugin/supervisor.go
+++ b/plugin/supervisor.go
@@ -39,7 +39,7 @@ func newSupervisor(pluginInfo *model.BundleInfo, apiImpl API, driver Driver, par
wrappedLogger := pluginInfo.WrapLogger(parentLogger)
hclogAdaptedLogger := &hclogAdapter{
- wrappedLogger: wrappedLogger.WithCallerSkip(1),
+ wrappedLogger: wrappedLogger,
extrasKey: "wrapped_extras",
}
diff --git a/plugin/supervisor_test.go b/plugin/supervisor_test.go
index 9719b97eb6..81b8d6a912 100644
--- a/plugin/supervisor_test.go
+++ b/plugin/supervisor_test.go
@@ -35,12 +35,8 @@ func testSupervisorInvalidExecutablePath(t *testing.T) {
ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "/foo/../../backend.exe"}}`), 0600)
bundle := model.BundleInfoForPath(dir)
- log := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- })
+ log := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
+ defer log.Shutdown()
supervisor, err := newSupervisor(bundle, nil, nil, log, nil)
assert.Nil(t, supervisor)
assert.Error(t, err)
@@ -54,12 +50,8 @@ func testSupervisorNonExistentExecutablePath(t *testing.T) {
ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "thisfileshouldnotexist"}}`), 0600)
bundle := model.BundleInfoForPath(dir)
- log := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- })
+ log := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
+ defer log.Shutdown()
supervisor, err := newSupervisor(bundle, nil, nil, log, nil)
require.Error(t, err)
require.Nil(t, supervisor)
@@ -84,12 +76,8 @@ func testSupervisorStartTimeout(t *testing.T) {
ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600)
bundle := model.BundleInfoForPath(dir)
- log := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- })
+ log := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
+ defer log.Shutdown()
supervisor, err := newSupervisor(bundle, nil, nil, log, nil)
require.Error(t, err)
require.Nil(t, supervisor)
diff --git a/services/imageproxy/local.go b/services/imageproxy/local.go
index e3379d30d9..1b663723e3 100644
--- a/services/imageproxy/local.go
+++ b/services/imageproxy/local.go
@@ -46,12 +46,7 @@ func makeLocalBackend(proxy *ImageProxy) *LocalBackend {
impl := imageproxy.NewProxy(proxy.HTTPService.MakeTransport(false), nil)
if proxy.Logger != nil {
- logger, err := proxy.Logger.StdLogAt(mlog.LevelDebug, mlog.String("image_proxy", "local"))
- if err != nil {
- mlog.Warn("Failed to initialize logger for image proxy", mlog.Err(err))
- }
-
- impl.Logger = logger
+ impl.Logger = proxy.Logger.With(mlog.String("image_proxy", "local")).StdLogger(mlog.LvlDebug)
}
baseURL, err := url.Parse(*proxy.ConfigService.Config().ServiceSettings.SiteURL)
diff --git a/services/remotecluster/mocks_test.go b/services/remotecluster/mocks_test.go
index 468396dfd1..4f102b5ac2 100644
--- a/services/remotecluster/mocks_test.go
+++ b/services/remotecluster/mocks_test.go
@@ -5,13 +5,8 @@ package remotecluster
import (
"context"
- "fmt"
- "strings"
- "sync"
"testing"
- "go.uber.org/zap/zapcore"
-
"github.com/mattermost/mattermost-server/v6/einterfaces"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin/plugintest/mock"
@@ -22,14 +17,16 @@ import (
type mockServer struct {
remotes []*model.RemoteCluster
- logger *mockLogger
+ logger *mlog.Logger
user *model.User
}
func newMockServer(t *testing.T, remotes []*model.RemoteCluster) *mockServer {
+ testLogger := mlog.CreateTestLogger(t, nil, mlog.StdAll...)
+
return &mockServer{
remotes: remotes,
- logger: &mockLogger{t: t},
+ logger: testLogger,
}
}
@@ -64,88 +61,3 @@ func (ms *mockServer) GetStore() store.Store {
return storeMock
}
func (ms *mockServer) Shutdown() { ms.logger.Shutdown() }
-
-type mockLogger struct {
- t *testing.T
- mux sync.Mutex
-}
-
-func (ml *mockLogger) IsLevelEnabled(level mlog.LogLevel) bool {
- return true
-}
-func (ml *mockLogger) Debug(s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log("debug", s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) Info(s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log("info", s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) Warn(s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log("warn", s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) Error(s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log("error", s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) Critical(s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log("crit", s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) Log(level mlog.LogLevel, s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log(level.Name, s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) LogM(levels []mlog.LogLevel, s string, flds ...mlog.Field) {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- if ml.t != nil {
- ml.t.Log(levelsToString(levels), s, fieldsToStrings(flds))
- }
-}
-func (ml *mockLogger) Shutdown() {
- ml.mux.Lock()
- defer ml.mux.Unlock()
- ml.t = nil
-}
-
-func levelsToString(levels []mlog.LogLevel) string {
- sb := strings.Builder{}
- for _, l := range levels {
- sb.WriteString(l.Name)
- sb.WriteString(",")
- }
- return sb.String()
-}
-
-func fieldsToStrings(fields []mlog.Field) []string {
- encoder := zapcore.NewMapObjectEncoder()
- for _, zapField := range fields {
- zapField.AddTo(encoder)
- }
-
- var result []string
- for k, v := range encoder.Fields {
- result = append(result, fmt.Sprintf("%s:%v", k, v))
- }
- return result
-}
diff --git a/services/sharedchannel/channelinvite_test.go b/services/sharedchannel/channelinvite_test.go
index 3a58b10f29..d1ee9978ad 100644
--- a/services/sharedchannel/channelinvite_test.go
+++ b/services/sharedchannel/channelinvite_test.go
@@ -23,7 +23,7 @@ type mockLogger struct {
mlog.LoggerIFace
}
-func (ml *mockLogger) Log(level mlog.LogLevel, s string, flds ...mlog.Field) {}
+func (ml *mockLogger) Log(level mlog.Level, s string, flds ...mlog.Field) {}
func TestOnReceiveChannelInvite(t *testing.T) {
t.Run("when msg payload is empty, it does nothing", func(t *testing.T) {
diff --git a/services/slackimport/main_test.go b/services/slackimport/main_test.go
index 63e8c1ccc6..ad8ff61f40 100644
--- a/services/slackimport/main_test.go
+++ b/services/slackimport/main_test.go
@@ -7,8 +7,6 @@ import (
"fmt"
"os"
"testing"
-
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
)
func TestMain(m *testing.M) {
@@ -22,8 +20,6 @@ func TestMain(m *testing.M) {
panic(fmt.Sprintf("Failed to set current working directory to %s: %s", "../..", err.Error()))
}
- mlog.DisableZap()
-
defer func() {
err := os.Chdir(prevDir)
if err != nil {
diff --git a/services/telemetry/telemetry.go b/services/telemetry/telemetry.go
index d5678ac2b4..acea4b9071 100644
--- a/services/telemetry/telemetry.go
+++ b/services/telemetry/telemetry.go
@@ -1228,7 +1228,7 @@ func (ts *TelemetryService) trackChannelModeration() {
func (ts *TelemetryService) initRudder(endpoint string, rudderKey string) {
if ts.rudderClient == nil {
config := rudder.Config{}
- config.Logger = rudder.StdLogger(ts.log.StdLog(mlog.String("source", "rudder")))
+ config.Logger = rudder.StdLogger(ts.log.With(mlog.String("source", "rudder")).StdLogger(mlog.LvlDebug))
config.Endpoint = endpoint
// For testing
if endpoint != RudderDataplaneURL {
diff --git a/services/telemetry/telemetry_test.go b/services/telemetry/telemetry_test.go
index c36a358e05..604b98d873 100644
--- a/services/telemetry/telemetry_test.go
+++ b/services/telemetry/telemetry_test.go
@@ -19,6 +19,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "github.com/mattermost/mattermost-server/v6/config"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/mattermost/mattermost-server/v6/plugin/plugintest"
@@ -40,6 +41,7 @@ func (fcs *FakeConfigService) AsymmetricSigningKey() *ecdsa.PrivateKey
func initializeMocks(cfg *model.Config) (*mocks.ServerIface, *storeMocks.Store, func(t *testing.T), func()) {
serverIfaceMock := &mocks.ServerIface{}
+ logger, _ := mlog.NewLogger()
configService := &FakeConfigService{cfg}
serverIfaceMock.On("Config").Return(cfg)
@@ -56,7 +58,7 @@ func initializeMocks(cfg *model.Config) (*mocks.ServerIface, *storeMocks.Store,
func(m *model.Manifest) plugin.API { return pluginsAPIMock },
nil,
pluginDir, webappPluginDir,
- mlog.NewLogger(&mlog.LoggerConfiguration{}),
+ logger,
nil)
serverIfaceMock.On("GetPluginsEnvironment").Return(pluginEnv, nil)
@@ -270,7 +272,14 @@ func TestRudderTelemetry(t *testing.T) {
defer cleanUp()
defer deferredAssertions(t)
- telemetryService := New(serverIfaceMock, storeMock, searchengine.NewBroker(cfg, nil), mlog.NewLogger(&mlog.LoggerConfiguration{}))
+ testLogger, _ := mlog.NewLogger()
+ logCfg, _ := config.MloggerConfigFromLoggerConfig(&cfg.LogSettings, nil, config.GetLogFileLocation)
+ if errCfg := testLogger.ConfigureTargets(logCfg); errCfg != nil {
+ panic("failed to configure test logger: " + errCfg.Error())
+ }
+ defer testLogger.Shutdown()
+
+ telemetryService := New(serverIfaceMock, storeMock, searchengine.NewBroker(cfg, nil), testLogger)
telemetryService.TelemetryID = telemetryID
telemetryService.rudderClient = nil
telemetryService.initRudder(server.URL, RudderKey)
diff --git a/services/users/main_test.go b/services/users/main_test.go
index 6a031adee5..f57d778116 100644
--- a/services/users/main_test.go
+++ b/services/users/main_test.go
@@ -7,7 +7,6 @@ import (
"flag"
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -26,8 +25,6 @@ func TestMain(m *testing.M) {
WithReadReplica: replicaFlag,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/shared/filestore/filesstore_test.go b/shared/filestore/filesstore_test.go
index dd53768e08..da909c93d6 100644
--- a/shared/filestore/filesstore_test.go
+++ b/shared/filestore/filesstore_test.go
@@ -33,12 +33,10 @@ type FileBackendTestSuite struct {
func TestLocalFileBackendTestSuite(t *testing.T) {
// Setup a global logger to catch tests logging outside of app context
// The global logger will be stomped by apps initializing but that's fine for testing. Ideally this won't happen.
- mlog.InitGlobalLogger(mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- }))
+ logger := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
+ defer logger.Shutdown()
+
+ mlog.InitGlobalLogger(logger)
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)
diff --git a/shared/mlog/default.go b/shared/mlog/default.go
index e7faa8c4c1..0567c01648 100644
--- a/shared/mlog/default.go
+++ b/shared/mlog/default.go
@@ -4,26 +4,32 @@
package mlog
import (
- "context"
+ "bytes"
"encoding/json"
- "errors"
"fmt"
"os"
-
- "github.com/mattermost/logr"
)
// defaultLog manually encodes the log to STDERR, providing a basic, default logging implementation
// before mlog is fully configured.
-func defaultLog(level, msg string, fields ...Field) {
+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 []Field `json:"fields,omitempty"`
+ Level string `json:"level"`
+ Message string `json:"msg"`
+ Fields map[string]string `json:"fields,omitempty"`
}{
- level,
+ level.Name,
msg,
- fields,
+ mFields,
}
if b, err := json.Marshal(log); err != nil {
@@ -33,67 +39,25 @@ func defaultLog(level, msg string, fields ...Field) {
}
}
-func defaultIsLevelEnabled(level LogLevel) bool {
+func defaultIsLevelEnabled(level Level) bool {
return true
}
-func defaultDebugLog(msg string, fields ...Field) {
- defaultLog("debug", msg, fields...)
+func defaultCustomMultiLog(lvl []Level, msg string, fields ...Field) {
+ for _, level := range lvl {
+ defaultLog(level, msg, fields...)
+ }
}
-func defaultInfoLog(msg string, fields ...Field) {
- defaultLog("info", msg, fields...)
-}
-
-func defaultWarnLog(msg string, fields ...Field) {
- defaultLog("warn", msg, fields...)
-}
-
-func defaultErrorLog(msg string, fields ...Field) {
- defaultLog("error", msg, fields...)
-}
-
-func defaultCriticalLog(msg string, fields ...Field) {
- // We map critical to error in zap, so be consistent.
- defaultLog("error", msg, fields...)
-}
-
-func defaultCustomLog(lvl LogLevel, msg string, fields ...Field) {
- // custom log levels are only output once log targets are configured.
-}
-
-func defaultCustomMultiLog(lvl []LogLevel, msg string, fields ...Field) {
- // custom log levels are only output once log targets are configured.
-}
-
-func defaultFlush(ctx context.Context) error {
- return nil
-}
-
-func defaultAdvancedConfig(cfg LogTargetCfg) error {
- // mlog.ConfigAdvancedConfig should not be called until default
- // logger is replaced with mlog.Logger instance.
- return errors.New("cannot config advanced logging on default logger")
-}
-
-func defaultAdvancedShutdown(ctx context.Context) error {
- return nil
-}
-
-func defaultAddTarget(targets ...logr.Target) error {
- // mlog.AddTarget should not be called until default
- // logger is replaced with mlog.Logger instance.
- return errors.New("cannot AddTarget on default logger")
-}
-
-func defaultRemoveTargets(ctx context.Context, f func(TargetInfo) bool) error {
- // mlog.RemoveTargets should not be called until default
- // logger is replaced with mlog.Logger instance.
- return errors.New("cannot RemoveTargets on default logger")
-}
-
-func defaultEnableMetrics(collector logr.MetricsCollector) error {
- // mlog.EnableMetrics should not be called until default
- // logger is replaced with mlog.Logger instance.
- return errors.New("cannot EnableMetrics on default logger")
+// 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/shared/mlog/errors.go b/shared/mlog/errors.go
deleted file mode 100644
index 93762fda57..0000000000
--- a/shared/mlog/errors.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "github.com/mattermost/logr"
-)
-
-// onLoggerError is called when the logging system encounters an error,
-// such as a target not able to write records. The targets will keep trying
-// however the error will be logged with a dedicated level that can be output
-// to a safe/always available target for monitoring or alerting.
-func onLoggerError(err error) {
- Log(LvlLogError, "advanced logging error", Err(err))
-}
-
-// onQueueFull is called when the main logger queue is full, indicating the
-// volume and frequency of log record creation is too high for the queue size
-// and/or the target latencies.
-func onQueueFull(rec *logr.LogRec, maxQueueSize int) bool {
- Log(LvlLogError, "main queue full, dropping record", Any("rec", rec))
- return true // drop record
-}
-
-// onTargetQueueFull is called when the main logger queue is full, indicating the
-// volume and frequency of log record creation is too high for the target's queue size
-// and/or the target latency.
-func onTargetQueueFull(target logr.Target, rec *logr.LogRec, maxQueueSize int) bool {
- Log(LvlLogError, "target queue full, dropping record", String("target", ""), Any("rec", rec))
- return true // drop record
-}
diff --git a/shared/mlog/global.go b/shared/mlog/global.go
index aba0664672..30b88c9b28 100644
--- a/shared/mlog/global.go
+++ b/shared/mlog/global.go
@@ -4,95 +4,119 @@
package mlog
import (
- "context"
- "log"
- "sync/atomic"
-
- "github.com/mattermost/logr"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
+ "sync"
)
-var globalLogger *Logger
+var (
+ globalLogger *Logger
+ muxGlobalLogger sync.RWMutex
+)
func InitGlobalLogger(logger *Logger) {
- // Clean up previous instance.
- if globalLogger != nil && globalLogger.logrLogger != nil {
- globalLogger.logrLogger.Logr().Shutdown()
+ 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)
}
- glob := *logger
- glob.zap = glob.zap.WithOptions(zap.AddCallerSkip(1))
- globalLogger = &glob
- IsLevelEnabled = globalLogger.IsLevelEnabled
- Debug = globalLogger.Debug
- Info = globalLogger.Info
- Warn = globalLogger.Warn
- Error = globalLogger.Error
- Critical = globalLogger.Critical
- Log = globalLogger.Log
- LogM = globalLogger.LogM
- Flush = globalLogger.Flush
- ConfigAdvancedLogging = globalLogger.ConfigAdvancedLogging
- ShutdownAdvancedLogging = globalLogger.ShutdownAdvancedLogging
- AddTarget = globalLogger.AddTarget
- RemoveTargets = globalLogger.RemoveTargets
- EnableMetrics = globalLogger.EnableMetrics
+ return logger.IsLevelEnabled(level)
}
-// logWriterFunc provides access to mlog via io.Writer, so the standard logger
-// can be redirected to use mlog and whatever targets are defined.
-type logWriterFunc func([]byte) (int, error)
-
-func (lw logWriterFunc) Write(p []byte) (int, error) {
- return lw(p)
-}
-
-func RedirectStdLog(logger *Logger) {
- if atomic.LoadInt32(&disableZap) == 0 {
- zap.RedirectStdLogAt(logger.zap.With(zap.String("source", "stdlog")).WithOptions(zap.AddCallerSkip(-2)), zapcore.ErrorLevel)
+// 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...)
+}
- writer := func(p []byte) (int, error) {
- Log(LvlStdLog, string(p))
- return len(p), nil
+// 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
}
- log.SetOutput(logWriterFunc(writer))
+ logger.LogM(levels, msg, fields...)
}
-type IsLevelEnabledFunc func(LogLevel) bool
-type LogFunc func(string, ...Field)
-type LogFuncCustom func(LogLevel, string, ...Field)
-type LogFuncCustomMulti func([]LogLevel, string, ...Field)
-type FlushFunc func(context.Context) error
-type ConfigFunc func(cfg LogTargetCfg) error
-type ShutdownFunc func(context.Context) error
-type AddTargetFunc func(...logr.Target) error
-type RemoveTargetsFunc func(context.Context, func(TargetInfo) bool) error
-type EnableMetricsFunc func(logr.MetricsCollector) error
-
-// DON'T USE THIS Modify the level on the app logger
-func GloballyDisableDebugLogForTest() {
- globalLogger.consoleLevel.SetLevel(zapcore.ErrorLevel)
+// 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...)
}
-// DON'T USE THIS Modify the level on the app logger
-func GloballyEnableDebugLogForTest() {
- globalLogger.consoleLevel.SetLevel(zapcore.DebugLevel)
+// 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...)
}
-var IsLevelEnabled IsLevelEnabledFunc = defaultIsLevelEnabled
-var Debug LogFunc = defaultDebugLog
-var Info LogFunc = defaultInfoLog
-var Warn LogFunc = defaultWarnLog
-var Error LogFunc = defaultErrorLog
-var Critical LogFunc = defaultCriticalLog
-var Log LogFuncCustom = defaultCustomLog
-var LogM LogFuncCustomMulti = defaultCustomMultiLog
-var Flush FlushFunc = defaultFlush
+// 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...)
+}
-var ConfigAdvancedLogging ConfigFunc = defaultAdvancedConfig
-var ShutdownAdvancedLogging ShutdownFunc = defaultAdvancedShutdown
-var AddTarget AddTargetFunc = defaultAddTarget
-var RemoveTargets RemoveTargetsFunc = defaultRemoveTargets
-var EnableMetrics EnableMetricsFunc = defaultEnableMetrics
+// 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.
+func Critical(msg string, fields ...Field) {
+ logger := getGlobalLogger()
+ if logger == nil {
+ defaultLog(LvlCritical, msg, fields...)
+ return
+ }
+ logger.Critical(msg, fields...)
+}
diff --git a/shared/mlog/global_test.go b/shared/mlog/global_test.go
index 8589d1a8b7..a3e47ebdce 100644
--- a/shared/mlog/global_test.go
+++ b/shared/mlog/global_test.go
@@ -4,6 +4,8 @@
package mlog_test
import (
+ "encoding/json"
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -29,83 +31,86 @@ func TestLoggingBeforeInitialized(t *testing.T) {
func TestLoggingAfterInitialized(t *testing.T) {
testCases := []struct {
- Description string
- LoggerConfiguration *mlog.LoggerConfiguration
- ExpectedLogs []string
+ description string
+ cfg mlog.TargetCfg
+ expectedLogs []string
}{
{
"file logging, json, debug",
- &mlog.LoggerConfiguration{
- EnableConsole: false,
- EnableFile: true,
- FileJson: true,
- FileLevel: mlog.LevelDebug,
+ mlog.TargetCfg{
+ Type: "file",
+ Format: "json",
+ FormatOptions: json.RawMessage(`{"enable_caller":true}`),
+ Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError, mlog.LvlWarn, mlog.LvlInfo, mlog.LvlDebug},
},
[]string{
- `{"level":"debug","ts":0,"caller":"mlog/global_test.go:0","msg":"real debug log"}`,
- `{"level":"info","ts":0,"caller":"mlog/global_test.go:0","msg":"real info log"}`,
- `{"level":"warn","ts":0,"caller":"mlog/global_test.go:0","msg":"real warning log"}`,
- `{"level":"error","ts":0,"caller":"mlog/global_test.go:0","msg":"real error log"}`,
- `{"level":"error","ts":0,"caller":"mlog/global_test.go:0","msg":"real critical log"}`,
+ `{"timestamp":0,"level":"debug","msg":"real debug log","caller":"mlog/global_test.go:0"}`,
+ `{"timestamp":0,"level":"info","msg":"real info log","caller":"mlog/global_test.go:0"}`,
+ `{"timestamp":0,"level":"warn","msg":"real warning log","caller":"mlog/global_test.go:0"}`,
+ `{"timestamp":0,"level":"error","msg":"real error log","caller":"mlog/global_test.go:0"}`,
+ `{"timestamp":0,"level":"critical","msg":"real critical log","caller":"mlog/global_test.go:0"}`,
},
},
{
"file logging, json, error",
- &mlog.LoggerConfiguration{
- EnableConsole: false,
- EnableFile: true,
- FileJson: true,
- FileLevel: mlog.LevelError,
+ mlog.TargetCfg{
+ Type: "file",
+ Format: "json",
+ FormatOptions: json.RawMessage(`{"enable_caller":true}`),
+ Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError},
},
[]string{
- `{"level":"error","ts":0,"caller":"mlog/global_test.go:0","msg":"real error log"}`,
- `{"level":"error","ts":0,"caller":"mlog/global_test.go:0","msg":"real critical log"}`,
+ `{"timestamp":0,"level":"error","msg":"real error log","caller":"mlog/global_test.go:0"}`,
+ `{"timestamp":0,"level":"critical","msg":"real critical log","caller":"mlog/global_test.go:0"}`,
},
},
{
"file logging, non-json, debug",
- &mlog.LoggerConfiguration{
- EnableConsole: false,
- EnableFile: true,
- FileJson: false,
- FileLevel: mlog.LevelDebug,
+ mlog.TargetCfg{
+ Type: "file",
+ Format: "plain",
+ FormatOptions: json.RawMessage(`{"delim":" | ", "enable_caller":true}`),
+ Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError, mlog.LvlWarn, mlog.LvlInfo, mlog.LvlDebug},
},
[]string{
- `TIME debug mlog/global_test.go:0 real debug log`,
- `TIME info mlog/global_test.go:0 real info log`,
- `TIME warn mlog/global_test.go:0 real warning log`,
- `TIME error mlog/global_test.go:0 real error log`,
- `TIME error mlog/global_test.go:0 real critical log`,
+ `debug | TIME | real debug log | caller="mlog/global_test.go:0"`,
+ `info | TIME | real info log | caller="mlog/global_test.go:0"`,
+ `warn | TIME | real warning log | caller="mlog/global_test.go:0"`,
+ `error | TIME | real error log | caller="mlog/global_test.go:0"`,
+ `critical | TIME | real critical log | caller="mlog/global_test.go:0"`,
},
},
{
"file logging, non-json, error",
- &mlog.LoggerConfiguration{
- EnableConsole: false,
- EnableFile: true,
- FileJson: false,
- FileLevel: mlog.LevelError,
+ mlog.TargetCfg{
+ Type: "file",
+ Format: "plain",
+ FormatOptions: json.RawMessage(`{"delim":" | ", "enable_caller":true}`),
+ Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError},
},
[]string{
- `TIME error mlog/global_test.go:0 real error log`,
- `TIME error mlog/global_test.go:0 real critical log`,
+ `error | TIME | real error log | caller="mlog/global_test.go:0"`,
+ `critical | TIME | real critical log | caller="mlog/global_test.go:0"`,
},
},
}
for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
+ t.Run(testCase.description, func(t *testing.T) {
var filePath string
- if testCase.LoggerConfiguration.EnableFile {
+ if testCase.cfg.Type == "file" {
tempDir, err := ioutil.TempDir(os.TempDir(), "TestLoggingAfterInitialized")
require.NoError(t, err)
defer os.Remove(tempDir)
filePath = filepath.Join(tempDir, "file.log")
- testCase.LoggerConfiguration.FileLocation = filePath
+ testCase.cfg.Options = json.RawMessage(fmt.Sprintf(`{"filename": "%s"}`, filePath))
}
- logger := mlog.NewLogger(testCase.LoggerConfiguration)
+ logger, _ := mlog.NewLogger()
+ err := logger.ConfigureTargets(map[string]mlog.TargetCfg{testCase.description: testCase.cfg})
+ require.NoError(t, err)
+
mlog.InitGlobalLogger(logger)
mlog.Debug("real debug log")
@@ -114,32 +119,26 @@ func TestLoggingAfterInitialized(t *testing.T) {
mlog.Error("real error log")
mlog.Critical("real critical log")
- if testCase.LoggerConfiguration.EnableFile {
+ logger.Shutdown()
+
+ if testCase.cfg.Type == "file" {
logs, err := ioutil.ReadFile(filePath)
require.NoError(t, err)
actual := strings.TrimSpace(string(logs))
- if testCase.LoggerConfiguration.FileJson {
- reTs := regexp.MustCompile(`"ts":[0-9\.]+`)
+ if testCase.cfg.Format == "json" {
+ reTs := regexp.MustCompile(`"timestamp":"[0-9\.\-\:\sZ]+"`)
reCaller := regexp.MustCompile(`"caller":"([^"]+):[0-9\.]+"`)
- actual = reTs.ReplaceAllString(actual, `"ts":0`)
+ actual = reTs.ReplaceAllString(actual, `"timestamp":0`)
actual = reCaller.ReplaceAllString(actual, `"caller":"$1:0"`)
} else {
- actualRows := strings.Split(actual, "\n")
- for i, actualRow := range actualRows {
- actualFields := strings.Split(actualRow, "\t")
- if len(actualFields) > 3 {
- actualFields[0] = "TIME"
- reCaller := regexp.MustCompile(`([^"]+):[0-9\.]+`)
- actualFields[2] = reCaller.ReplaceAllString(actualFields[2], "$1:0")
- actualRows[i] = strings.Join(actualFields, "\t")
- }
- }
-
- actual = strings.Join(actualRows, "\n")
+ reTs := regexp.MustCompile(`\[\d\d\d\d-\d\d-\d\d\s[0-9\:\.\s\-Z]+\]`)
+ reCaller := regexp.MustCompile(`caller="([^"]+):[0-9\.]+"`)
+ actual = reTs.ReplaceAllString(actual, "TIME")
+ actual = reCaller.ReplaceAllString(actual, `caller="$1:0"`)
}
- require.ElementsMatch(t, testCase.ExpectedLogs, strings.Split(actual, "\n"))
+ require.ElementsMatch(t, testCase.expectedLogs, strings.Split(actual, "\n"))
}
})
}
diff --git a/shared/mlog/human/entry.go b/shared/mlog/human/entry.go
deleted file mode 100644
index 1a49fdcaca..0000000000
--- a/shared/mlog/human/entry.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package human
-
-import (
- "fmt"
- "strings"
- "time"
-
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
-)
-
-type LogEntry struct {
- Time time.Time
- Level string
- Message string
- Caller string
- Fields []mlog.Field
-}
-
-// Provide default string representation. Used by SimpleWriter
-func (f LogEntry) String() string {
- var sb strings.Builder
- if !f.Time.IsZero() {
- sb.WriteString(f.Time.Format(time.RFC3339Nano))
- sb.WriteRune(' ')
- }
- if f.Level != "" {
- sb.WriteString(f.Level)
- sb.WriteRune(' ')
- }
- if f.Caller != "" {
- sb.WriteString(f.Caller)
- sb.WriteRune(' ')
- }
- for _, field := range f.Fields {
- sb.WriteString(field.Key)
- sb.WriteRune('=')
- sb.WriteString(fmt.Sprint(field.Interface))
- sb.WriteRune(' ')
- }
- if f.Message != "" {
- // If the message is multiple lines, start the whole message on a new line
- if strings.ContainsRune(f.Message, '\n') {
- sb.WriteRune('\n')
- }
- sb.WriteString(f.Message)
- }
-
- return sb.String()
-}
diff --git a/shared/mlog/human/logrus_writer.go b/shared/mlog/human/logrus_writer.go
deleted file mode 100644
index f086112fe0..0000000000
--- a/shared/mlog/human/logrus_writer.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package human
-
-import (
- "fmt"
- "io"
- "time"
-
- "github.com/sirupsen/logrus"
-)
-
-type LogrusWriter struct {
- logger *logrus.Logger
-}
-
-func (w *LogrusWriter) Write(e LogEntry) {
- if e.Level == "" {
- fmt.Fprintln(w.logger.Out, e.Message)
- return
- }
-
- lvl, err := logrus.ParseLevel(e.Level)
- if err != nil {
- fmt.Fprintln(w.logger.Out, err)
- lvl = logrus.TraceLevel + 1 // will invoke Println
- }
-
- logger := w.logger.WithTime(e.Time)
-
- if e.Caller != "" {
- // logrus has a system of reporting the caller, but there's no easy way to override it
- logger = logger.WithField("caller", e.Caller)
- }
-
- for _, field := range e.Fields {
- logger = logger.WithField(field.Key, field.Interface)
- }
-
- switch lvl {
- case logrus.PanicLevel:
- // Prevent panic from causing us to exit
- defer func() {
- recover()
- }()
- logger.Panic(e.Message)
- case logrus.FatalLevel:
- logger.Fatal(e.Message)
- case logrus.ErrorLevel:
- logger.Error(e.Message)
- case logrus.WarnLevel:
- logger.Warn(e.Message)
- case logrus.InfoLevel:
- logger.Info(e.Message)
- case logrus.DebugLevel:
- logger.Debug(e.Message)
- case logrus.TraceLevel:
- logger.Trace(e.Message)
- default:
- logger.Println(e.Message)
- }
-}
-
-func NewLogrusWriter(output io.Writer) *LogrusWriter {
- w := new(LogrusWriter)
- w.logger = logrus.New()
- w.logger.SetLevel(logrus.TraceLevel) // don't filter any logs
- w.logger.ExitFunc = func(int) {} // prevent Fatal from causing us to exit
- w.logger.SetReportCaller(false)
- w.logger.SetOutput(output)
- var tf logrus.TextFormatter
- tf.FullTimestamp = true
- tf.TimestampFormat = time.RFC3339Nano
- w.logger.SetFormatter(&tf)
- return w
-}
diff --git a/shared/mlog/human/parser.go b/shared/mlog/human/parser.go
deleted file mode 100644
index b4b45505df..0000000000
--- a/shared/mlog/human/parser.go
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package human
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "strconv"
- "strings"
- "time"
-
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
-)
-
-func ParseLogMessage(msg string) LogEntry {
- result, err := parseLogMessage(msg)
- if err != nil {
- // If failed to parse, just output a LogEntry where all fields are blank, but Message is the original string
- var result2 LogEntry
- result2.Message = msg
- return result2
- }
- return result
-}
-
-func parseLogMessage(msg string) (result LogEntry, err error) {
-
- // Note: This implementation uses a custom json decoding loop.
- // The primary advantage of this versus decoding directly into a map is to
- // preserve the order of the fields. This can be simplified if we end up
- // having the formatter sort fields alphabetically (logrus does by default)
-
- dec := json.NewDecoder(strings.NewReader(msg))
-
- // look for an initial "{"
- token, err := dec.Token()
- if err != nil {
- return result, err
- }
- d, ok := token.(json.Delim)
- if !ok || d != '{' {
- return result, fmt.Errorf("input is not a JSON object, found: %v", token)
- }
-
- // read all key-value pairs
- for dec.More() {
- key, err2 := dec.Token()
- if err2 != nil {
- return result, err2
- }
- skey, ok2 := key.(string)
- if !ok2 {
- return result, errors.New("key is not a value string")
- }
- if !dec.More() {
- return result, errors.New("missing value pair")
- }
-
- switch skey {
- case "ts":
- var ts json.Number
- if err2 := dec.Decode(&ts); err2 != nil {
- return result, err2
- }
- timeVal, err2 := numberToTime(ts)
- if err2 != nil {
- return result, err2
- }
- result.Time = timeVal
-
- case "level":
- s, err2 := decodeAsString(dec)
- if err2 != nil {
- return result, err2
- }
- result.Level = s
-
- case "msg":
- s, err2 := decodeAsString(dec)
- if err2 != nil {
- return result, err2
- }
- result.Message = s
-
- case "caller":
- s, err2 := decodeAsString(dec)
- if err2 != nil {
- return result, err2
- }
- result.Caller = s
-
- default:
- var p interface{}
- if err2 := dec.Decode(&p); err2 != nil {
- return result, err2
- }
- var f mlog.Field
- f.Key = skey
- f.Interface = p
- result.Fields = append(result.Fields, f)
- }
- }
-
- // read the "}"
- token, err = dec.Token()
- if err != nil {
- return result, err
- }
- d, ok = token.(json.Delim)
- if !ok || d != '}' {
- return result, fmt.Errorf("failed to read '}', read: %v", token)
- }
-
- // make sure nothing else trailing
- if token, err := dec.Token(); err != io.EOF {
- return result, err
- } else if token != nil {
- return result, errors.New("found trailing data")
- }
-
- return result, nil
-}
-
-// Translate a number into a time
-func numberToTime(v json.Number) (time.Time, error) {
- // Using floating point math to extract the nanoseconds leads to a time that doesn't exactly match the input
- // Instead, parse out the components from the string representation
-
- var t time.Time
-
- // First make sure it is a number...
- flt, err := v.Float64()
- if err != nil {
- return t, err
- }
-
- s := v.String()
-
- if strings.ContainsAny(s, "eE") {
- // input is in scientific notation. Convert to standard decimal notation
- s = strconv.FormatFloat(flt, 'f', -1, 64)
- }
-
- // extract the seconds and nanoseconds separately
- var nanos, sec int64
-
- parts := strings.SplitN(s, ".", 2)
- sec, err = strconv.ParseInt(parts[0], 10, 64)
- if err != nil {
- return t, err
- }
-
- if len(parts) == 2 {
- nanosText := parts[1] + "000000000"
- nanosText = nanosText[:9]
- nanos, err = strconv.ParseInt(nanosText, 10, 64)
- if err != nil {
- return t, err
- }
- }
-
- t = time.Unix(sec, nanos)
- return t, nil
-}
-
-// Decodes a value from JSON, coercing it to a string value as necessary
-func decodeAsString(dec *json.Decoder) (s string, err error) {
- var v interface{}
- if err = dec.Decode(&v); err != nil {
- return s, err
- }
- var ok bool
- if s, ok = v.(string); ok {
- return s, err
- }
- s = fmt.Sprint(v)
- return s, err
-}
diff --git a/shared/mlog/human/process.go b/shared/mlog/human/process.go
deleted file mode 100644
index ae31acdad3..0000000000
--- a/shared/mlog/human/process.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package human
-
-import (
- "bufio"
- "io"
-)
-
-type LogWriter interface {
- Write(e LogEntry)
-}
-
-// Read JSON logs from input and write formatted logs to the output
-func ProcessLogs(reader io.Reader, writer LogWriter) {
- scanner := bufio.NewScanner(reader)
- for scanner.Scan() {
- s := scanner.Text()
- e := ParseLogMessage(s)
- writer.Write(e)
- }
-}
diff --git a/shared/mlog/human/simple_writer.go b/shared/mlog/human/simple_writer.go
deleted file mode 100644
index 760ed91596..0000000000
--- a/shared/mlog/human/simple_writer.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package human
-
-import (
- "fmt"
- "io"
-)
-
-type SimpleWriter struct {
- out io.Writer
-}
-
-func (w *SimpleWriter) Write(e LogEntry) {
- fmt.Fprintln(w.out, e)
-}
-
-func NewSimpleWriter(out io.Writer) *SimpleWriter {
- w := new(SimpleWriter)
- w.out = out
- return w
-}
diff --git a/shared/mlog/levels.go b/shared/mlog/levels.go
index 872b129687..c0b3099643 100644
--- a/shared/mlog/levels.go
+++ b/shared/mlog/levels.go
@@ -3,49 +3,56 @@
package mlog
-// Standard levels
+import "github.com/mattermost/logr/v2"
+
+// Standard levels.
var (
- LvlPanic = LogLevel{ID: 0, Name: "panic", Stacktrace: true}
- LvlFatal = LogLevel{ID: 1, Name: "fatal", Stacktrace: true}
- LvlError = LogLevel{ID: 2, Name: "error"}
- LvlWarn = LogLevel{ID: 3, Name: "warn"}
- LvlInfo = LogLevel{ID: 4, Name: "info"}
- LvlDebug = LogLevel{ID: 5, Name: "debug"}
- LvlTrace = LogLevel{ID: 6, Name: "trace"}
+ 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 = LogLevel{ID: 10, Name: "stdlog"}
+ LvlStdLog = Level{ID: 10, Name: "stdlog"}
// used only by the logger
- LvlLogError = LogLevel{ID: 11, Name: "logerror", Stacktrace: true}
+ LvlLogError = Level{ID: 11, Name: "logerror", Stacktrace: true}
)
// Register custom (discrete) levels here.
-// !!!!! ID's must not exceed 32,768 !!!!!!
+// !!!!! Custom ID's must be between 20 and 32,768 !!!!!!
var (
// used by the audit system
- LvlAuditAPI = LogLevel{ID: 100, Name: "audit-api"}
- LvlAuditContent = LogLevel{ID: 101, Name: "audit-content"}
- LvlAuditPerms = LogLevel{ID: 102, Name: "audit-permissions"}
- LvlAuditCLI = LogLevel{ID: 103, Name: "audit-cli"}
+ 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 = LogLevel{ID: 120, Name: "TcpLogTarget"}
+ LvlTCPLogTarget = Level{ID: 120, Name: "TcpLogTarget"}
// used by Remote Cluster Service
- LvlRemoteClusterServiceDebug = LogLevel{ID: 130, Name: "RemoteClusterServiceDebug"}
- LvlRemoteClusterServiceError = LogLevel{ID: 131, Name: "RemoteClusterServiceError"}
- LvlRemoteClusterServiceWarn = LogLevel{ID: 132, Name: "RemoteClusterServiceWarn"}
+ 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 = LogLevel{ID: 200, Name: "SharedChannelServiceDebug"}
- LvlSharedChannelServiceError = LogLevel{ID: 201, Name: "SharedChannelServiceError"}
- LvlSharedChannelServiceWarn = LogLevel{ID: 202, Name: "SharedChannelServiceWarn"}
- LvlSharedChannelServiceMessagesInbound = LogLevel{ID: 203, Name: "SharedChannelServiceMsgInbound"}
- LvlSharedChannelServiceMessagesOutbound = LogLevel{ID: 204, Name: "SharedChannelServiceMsgOutbound"}
+ 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"}
- // add more here ...
+ // Focalboard
+ LvlFBTelemetry = Level{ID: 9000, Name: "telemetry"}
+ LvlFBMetrics = Level{ID: 9001, Name: "metrics"}
)
-// Combinations for LogM (log multi)
+// Combinations for LogM (log multi).
var (
- MLvlAuditAll = []LogLevel{LvlAuditAPI, LvlAuditContent, LvlAuditPerms, LvlAuditCLI}
+ MLvlAuditAll = []Level{LvlAuditAPI, LvlAuditContent, LvlAuditPerms, LvlAuditCLI}
)
diff --git a/shared/mlog/log.go b/shared/mlog/log.go
deleted file mode 100644
index d50fc1230e..0000000000
--- a/shared/mlog/log.go
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "context"
- "fmt"
- "io"
- "log"
- "os"
- "sync"
- "sync/atomic"
- "time"
-
- "github.com/mattermost/logr"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- "gopkg.in/natefinch/lumberjack.v2"
-)
-
-const (
- // Very verbose messages for debugging specific issues
- LevelDebug = "debug"
- // Default log level, informational
- LevelInfo = "info"
- // Warnings are messages about possible issues
- LevelWarn = "warn"
- // Errors are messages about things we know are problems
- LevelError = "error"
-
- // DefaultFlushTimeout is the default amount of time mlog.Flush will wait
- // before timing out.
- DefaultFlushTimeout = time.Second * 5
-)
-
-var (
- // disableZap is set when Zap should be disabled and Logr used instead.
- // This is needed for unit testing as Zap has no shutdown capabilities
- // and holds file handles until process exit. Currently unit test create
- // many server instances, and thus many Zap log files.
- // This flag will be removed when Zap is permanently replaced.
- disableZap int32
-)
-
-// Type and function aliases from zap to limit the libraries scope into MM code
-type Field = zapcore.Field
-
-var Int64 = zap.Int64
-var Int32 = zap.Int32
-var Int = zap.Int
-var Uint32 = zap.Uint32
-var String = zap.String
-var Any = zap.Any
-var Err = zap.Error
-var NamedErr = zap.NamedError
-var Bool = zap.Bool
-var Duration = zap.Duration
-
-type LoggerIFace interface {
- IsLevelEnabled(LogLevel) bool
- Debug(string, ...Field)
- Info(string, ...Field)
- Warn(string, ...Field)
- Error(string, ...Field)
- Critical(string, ...Field)
- Log(LogLevel, string, ...Field)
- LogM([]LogLevel, string, ...Field)
-}
-
-type TargetInfo logr.TargetInfo
-
-type LoggerConfiguration struct {
- EnableConsole bool
- ConsoleJson bool
- EnableColor bool
- ConsoleLevel string
- EnableFile bool
- FileJson bool
- FileLevel string
- FileLocation string
-}
-
-type Logger struct {
- zap *zap.Logger
- consoleLevel zap.AtomicLevel
- fileLevel zap.AtomicLevel
- logrLogger *logr.Logger
- mutex *sync.RWMutex
-}
-
-func getZapLevel(level string) zapcore.Level {
- switch level {
- case LevelInfo:
- return zapcore.InfoLevel
- case LevelWarn:
- return zapcore.WarnLevel
- case LevelDebug:
- return zapcore.DebugLevel
- case LevelError:
- return zapcore.ErrorLevel
- default:
- return zapcore.InfoLevel
- }
-}
-
-func makeEncoder(json, color bool) zapcore.Encoder {
- encoderConfig := zap.NewProductionEncoderConfig()
- if json {
- return zapcore.NewJSONEncoder(encoderConfig)
- }
-
- if color {
- encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
- }
- encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
- return zapcore.NewConsoleEncoder(encoderConfig)
-}
-
-func NewLogger(config *LoggerConfiguration) *Logger {
- cores := []zapcore.Core{}
- logger := &Logger{
- consoleLevel: zap.NewAtomicLevelAt(getZapLevel(config.ConsoleLevel)),
- fileLevel: zap.NewAtomicLevelAt(getZapLevel(config.FileLevel)),
- logrLogger: newLogr(),
- mutex: &sync.RWMutex{},
- }
-
- if config.EnableConsole {
- writer := zapcore.Lock(os.Stderr)
- core := zapcore.NewCore(makeEncoder(config.ConsoleJson, config.EnableColor), writer, logger.consoleLevel)
- cores = append(cores, core)
- }
-
- if config.EnableFile {
- if atomic.LoadInt32(&disableZap) != 0 {
- t := &LogTarget{
- Type: "file",
- Format: "json",
- Levels: mlogLevelToLogrLevels(config.FileLevel),
- MaxQueueSize: DefaultMaxTargetQueue,
- Options: []byte(fmt.Sprintf(`{"Filename":"%s", "MaxSizeMB":%d, "Compress":%t}`,
- config.FileLocation, 100, true)),
- }
- if !config.FileJson {
- t.Format = "plain"
- }
- if tgt, err := NewLogrTarget("mlogFile", t); err == nil {
- logger.logrLogger.Logr().AddTarget(tgt)
- } else {
- Error("error creating mlogFile", Err(err))
- }
- } else {
- writer := zapcore.AddSync(&lumberjack.Logger{
- Filename: config.FileLocation,
- MaxSize: 100,
- Compress: true,
- })
-
- core := zapcore.NewCore(makeEncoder(config.FileJson, false), writer, logger.fileLevel)
- cores = append(cores, core)
- }
- }
-
- combinedCore := zapcore.NewTee(cores...)
-
- logger.zap = zap.New(combinedCore,
- zap.AddCaller(),
- )
- return logger
-}
-
-func (l *Logger) ChangeLevels(config *LoggerConfiguration) {
- l.consoleLevel.SetLevel(getZapLevel(config.ConsoleLevel))
- l.fileLevel.SetLevel(getZapLevel(config.FileLevel))
-}
-
-func (l *Logger) SetConsoleLevel(level string) {
- l.consoleLevel.SetLevel(getZapLevel(level))
-}
-
-func (l *Logger) With(fields ...Field) *Logger {
- newLogger := *l
- newLogger.zap = newLogger.zap.With(fields...)
- if newLogger.getLogger() != nil {
- ll := newLogger.getLogger().WithFields(zapToLogr(fields))
- newLogger.logrLogger = &ll
- }
- return &newLogger
-}
-
-func (l *Logger) StdLog(fields ...Field) *log.Logger {
- return zap.NewStdLog(l.With(fields...).zap.WithOptions(getStdLogOption()))
-}
-
-// StdLogAt returns *log.Logger which writes to supplied zap logger at required level.
-func (l *Logger) StdLogAt(level string, fields ...Field) (*log.Logger, error) {
- return zap.NewStdLogAt(l.With(fields...).zap.WithOptions(getStdLogOption()), getZapLevel(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 accordingly
-func (l *Logger) StdLogWriter() io.Writer {
- newLogger := *l
- newLogger.zap = newLogger.zap.WithOptions(zap.AddCallerSkip(4), getStdLogOption())
- f := newLogger.Info
- return &loggerWriter{f}
-}
-
-func (l *Logger) WithCallerSkip(skip int) *Logger {
- newLogger := *l
- newLogger.zap = newLogger.zap.WithOptions(zap.AddCallerSkip(skip))
- return &newLogger
-}
-
-// Made for the plugin interface, wraps mlog in a simpler interface
-// at the cost of performance
-func (l *Logger) Sugar() *SugarLogger {
- return &SugarLogger{
- wrappedLogger: l,
- zapSugar: l.zap.Sugar(),
- }
-}
-
-func (l *Logger) IsLevelEnabled(level LogLevel) bool {
- return isLevelEnabled(l.getLogger(), logr.Level(level))
-}
-
-func (l *Logger) Debug(message string, fields ...Field) {
- l.zap.Debug(message, fields...)
- if isLevelEnabled(l.getLogger(), logr.Debug) {
- l.getLogger().WithFields(zapToLogr(fields)).Debug(message)
- }
-}
-
-func (l *Logger) Info(message string, fields ...Field) {
- l.zap.Info(message, fields...)
- if isLevelEnabled(l.getLogger(), logr.Info) {
- l.getLogger().WithFields(zapToLogr(fields)).Info(message)
- }
-}
-
-func (l *Logger) Warn(message string, fields ...Field) {
- l.zap.Warn(message, fields...)
- if isLevelEnabled(l.getLogger(), logr.Warn) {
- l.getLogger().WithFields(zapToLogr(fields)).Warn(message)
- }
-}
-
-func (l *Logger) Error(message string, fields ...Field) {
- l.zap.Error(message, fields...)
- if isLevelEnabled(l.getLogger(), logr.Error) {
- l.getLogger().WithFields(zapToLogr(fields)).Error(message)
- }
-}
-
-func (l *Logger) Critical(message string, fields ...Field) {
- l.zap.Error(message, fields...)
- if isLevelEnabled(l.getLogger(), logr.Error) {
- l.getLogger().WithFields(zapToLogr(fields)).Error(message)
- }
-}
-
-func (l *Logger) Log(level LogLevel, message string, fields ...Field) {
- l.getLogger().WithFields(zapToLogr(fields)).Log(logr.Level(level), message)
-}
-
-func (l *Logger) LogM(levels []LogLevel, message string, fields ...Field) {
- var logger *logr.Logger
- for _, lvl := range levels {
- if isLevelEnabled(l.getLogger(), logr.Level(lvl)) {
- // don't create logger with fields unless at least one level is active.
- if logger == nil {
- l := l.getLogger().WithFields(zapToLogr(fields))
- logger = &l
- }
- logger.Log(logr.Level(lvl), message)
- }
- }
-}
-
-func (l *Logger) Flush(cxt context.Context) error {
- return l.getLogger().Logr().FlushWithTimeout(cxt)
-}
-
-// ShutdownAdvancedLogging stops the logger from accepting new log records and tries to
-// flush queues within the context timeout. Once complete all targets are shutdown
-// and any resources released.
-func (l *Logger) ShutdownAdvancedLogging(cxt context.Context) error {
- err := l.getLogger().Logr().ShutdownWithTimeout(cxt)
- l.setLogger(newLogr())
- return err
-}
-
-// ConfigAdvancedLoggingConfig (re)configures advanced logging based on the
-// specified log targets. This is the easiest way to get the advanced logger
-// configured via a config source such as file.
-func (l *Logger) ConfigAdvancedLogging(targets LogTargetCfg) error {
- if err := l.ShutdownAdvancedLogging(context.Background()); err != nil {
- Error("error shutting down previous logger", Err(err))
- }
-
- err := logrAddTargets(l.getLogger(), targets)
- return err
-}
-
-// AddTarget adds one or more logr.Target to the advanced logger. This is the preferred method
-// to add custom targets or provide configuration that cannot be expressed via a
-// config source.
-func (l *Logger) AddTarget(targets ...logr.Target) error {
- return l.getLogger().Logr().AddTarget(targets...)
-}
-
-// RemoveTargets selectively removes targets that were previously added to this logger instance
-// using the passed in filter function. The filter function should return true to remove the target
-// and false to keep it.
-func (l *Logger) RemoveTargets(ctx context.Context, f func(ti TargetInfo) bool) error {
- // Use locally defined TargetInfo type so we don't spread Logr dependencies.
- fc := func(tic logr.TargetInfo) bool {
- return f(TargetInfo(tic))
- }
- return l.getLogger().Logr().RemoveTargets(ctx, fc)
-}
-
-// EnableMetrics enables metrics collection by supplying a MetricsCollector.
-// The MetricsCollector provides counters and gauges that are updated by log targets.
-func (l *Logger) EnableMetrics(collector logr.MetricsCollector) error {
- return l.getLogger().Logr().SetMetricsCollector(collector)
-}
-
-// getLogger is a concurrent safe getter of the logr logger
-func (l *Logger) getLogger() *logr.Logger {
- defer l.mutex.RUnlock()
- l.mutex.RLock()
- return l.logrLogger
-}
-
-// setLogger is a concurrent safe setter of the logr logger
-func (l *Logger) setLogger(logger *logr.Logger) {
- defer l.mutex.Unlock()
- l.mutex.Lock()
- l.logrLogger = logger
-}
-
-// DisableZap is called to disable Zap, and Logr will be used instead. Any Logger
-// instances created after this call will only use Logr.
-//
-// This is needed for unit testing as Zap has no shutdown capabilities
-// and holds file handles until process exit. Currently unit tests create
-// many server instances, and thus many Zap log file handles.
-//
-// This method will be removed when Zap is permanently replaced.
-func DisableZap() {
- atomic.StoreInt32(&disableZap, 1)
-}
-
-// EnableZap re-enables Zap such that any Logger instances created after this
-// call will allow Zap targets.
-func EnableZap() {
- atomic.StoreInt32(&disableZap, 0)
-}
diff --git a/shared/mlog/log_test.go b/shared/mlog/log_test.go
deleted file mode 100644
index cda0498625..0000000000
--- a/shared/mlog/log_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog_test
-
-import (
- "context"
- "sync"
- "testing"
-
- "github.com/stretchr/testify/require"
-
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
-)
-
-// Test race condition when shutting down advanced logging. This test must run with the -race flag in order to verify
-// that there is no race.
-func TestLogger_ShutdownAdvancedLoggingRace(t *testing.T) {
- logger := mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- EnableFile: false,
- FileLevel: mlog.LevelInfo,
- })
- started := make(chan bool)
- ctx, cancel := context.WithCancel(context.Background())
- var wg sync.WaitGroup
-
- wg.Add(1)
- go func() {
- defer wg.Done()
- started <- true
-
- for {
- select {
- case <-ctx.Done():
- return
- default:
- logger.Debug("testing...")
- }
- }
- }()
-
- <-started
-
- err := logger.ShutdownAdvancedLogging(ctx)
- require.NoError(t, err)
-
- cancel()
- wg.Wait()
-}
diff --git a/shared/mlog/logr.go b/shared/mlog/logr.go
deleted file mode 100644
index b253dfbc6c..0000000000
--- a/shared/mlog/logr.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "os"
-
- "github.com/hashicorp/go-multierror"
- "github.com/mattermost/logr"
- logrFmt "github.com/mattermost/logr/format"
- "github.com/mattermost/logr/target"
- "go.uber.org/zap/zapcore"
-)
-
-const (
- DefaultMaxTargetQueue = 1000
- DefaultSysLogPort = 514
-)
-
-type LogLevel struct {
- ID logr.LevelID
- Name string
- Stacktrace bool
-}
-
-type LogTarget struct {
- Type string // one of "console", "file", "tcp", "syslog", "none".
- Format string // one of "json", "plain"
- Levels []LogLevel
- Options json.RawMessage
- MaxQueueSize int
-}
-
-type LogTargetCfg map[string]*LogTarget
-type LogrCleanup func() error
-
-func newLogr() *logr.Logger {
- lgr := &logr.Logr{}
- lgr.OnExit = func(int) {}
- lgr.OnPanic = func(interface{}) {}
- lgr.OnLoggerError = onLoggerError
- lgr.OnQueueFull = onQueueFull
- lgr.OnTargetQueueFull = onTargetQueueFull
-
- logger := lgr.NewLogger()
- return &logger
-}
-
-func logrAddTargets(logger *logr.Logger, targets LogTargetCfg) error {
- lgr := logger.Logr()
- var errs error
- for name, t := range targets {
- target, err := NewLogrTarget(name, t)
- if err != nil {
- errs = multierror.Append(err)
- continue
- }
- if target != nil {
- target.SetName(name)
- lgr.AddTarget(target)
- }
- }
- return errs
-}
-
-// NewLogrTarget creates a `logr.Target` based on a target config.
-// Can be used when parsing custom config files, or when programmatically adding
-// built-in targets. Use `mlog.AddTarget` to add custom targets.
-func NewLogrTarget(name string, t *LogTarget) (logr.Target, error) {
- formatter, err := newFormatter(name, t.Format)
- if err != nil {
- return nil, err
- }
- filter := newFilter(t.Levels)
-
- if t.MaxQueueSize == 0 {
- t.MaxQueueSize = DefaultMaxTargetQueue
- }
-
- switch t.Type {
- case "console":
- return newConsoleTarget(name, t, filter, formatter)
- case "file":
- return newFileTarget(name, t, filter, formatter)
- case "syslog":
- return newSyslogTarget(name, t, filter, formatter)
- case "tcp":
- return newTCPTarget(name, t, filter, formatter)
- case "none":
- return nil, nil
- }
- return nil, fmt.Errorf("invalid type '%s' for target %s", t.Type, name)
-}
-
-func newFilter(levels []LogLevel) logr.Filter {
- filter := &logr.CustomFilter{}
- for _, lvl := range levels {
- filter.Add(logr.Level(lvl))
- }
- return filter
-}
-
-func newFormatter(name string, format string) (logr.Formatter, error) {
- switch format {
- case "json", "":
- return &logrFmt.JSON{}, nil
- case "plain":
- return &logrFmt.Plain{Delim: " | "}, nil
- default:
- return nil, fmt.Errorf("invalid format '%s' for target %s", format, name)
- }
-}
-
-func newConsoleTarget(name string, t *LogTarget, filter logr.Filter, formatter logr.Formatter) (logr.Target, error) {
- type consoleOptions struct {
- Out string `json:"Out"`
- }
- options := &consoleOptions{}
- if err := json.Unmarshal(t.Options, options); err != nil {
- return nil, err
- }
-
- var w io.Writer
- switch options.Out {
- case "stdout", "":
- w = os.Stdout
- case "stderr":
- w = os.Stderr
- default:
- return nil, fmt.Errorf("invalid out '%s' for target %s", options.Out, name)
- }
-
- newTarget := target.NewWriterTarget(filter, formatter, w, t.MaxQueueSize)
- return newTarget, nil
-}
-
-func newFileTarget(name string, t *LogTarget, filter logr.Filter, formatter logr.Formatter) (logr.Target, error) {
- type fileOptions struct {
- Filename string `json:"Filename"`
- MaxSize int `json:"MaxSizeMB"`
- MaxAge int `json:"MaxAgeDays"`
- MaxBackups int `json:"MaxBackups"`
- Compress bool `json:"Compress"`
- }
- options := &fileOptions{}
- if err := json.Unmarshal(t.Options, options); err != nil {
- return nil, err
- }
- return newFileTargetWithOpts(name, t, target.FileOptions(*options), filter, formatter)
-}
-
-func newFileTargetWithOpts(name string, t *LogTarget, opts target.FileOptions, filter logr.Filter, formatter logr.Formatter) (logr.Target, error) {
- if opts.Filename == "" {
- return nil, fmt.Errorf("missing 'Filename' option for target %s", name)
- }
- if err := checkFileWritable(opts.Filename); err != nil {
- return nil, fmt.Errorf("error writing to 'Filename' for target %s: %w", name, err)
- }
-
- newTarget := target.NewFileTarget(filter, formatter, opts, t.MaxQueueSize)
- return newTarget, nil
-}
-
-func newSyslogTarget(name string, t *LogTarget, filter logr.Filter, formatter logr.Formatter) (logr.Target, error) {
- options := &SyslogParams{}
- if err := json.Unmarshal(t.Options, options); err != nil {
- return nil, err
- }
-
- if options.IP == "" {
- return nil, fmt.Errorf("missing 'IP' option for target %s", name)
- }
- if options.Port == 0 {
- options.Port = DefaultSysLogPort
- }
- return NewSyslogTarget(filter, formatter, options, t.MaxQueueSize)
-}
-
-func newTCPTarget(name string, t *LogTarget, filter logr.Filter, formatter logr.Formatter) (logr.Target, error) {
- options := &TCPParams{}
- if err := json.Unmarshal(t.Options, options); err != nil {
- return nil, err
- }
-
- if options.IP == "" {
- return nil, fmt.Errorf("missing 'IP' option for target %s", name)
- }
- if options.Port == 0 {
- return nil, fmt.Errorf("missing 'Port' option for target %s", name)
- }
- return NewTCPTarget(filter, formatter, options, t.MaxQueueSize)
-}
-
-func checkFileWritable(filename string) error {
- // try opening/creating the file for writing
- file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600)
- if err != nil {
- return err
- }
- file.Close()
- return nil
-}
-
-func isLevelEnabled(logger *logr.Logger, level logr.Level) bool {
- if logger == nil || logger.Logr() == nil {
- return false
- }
-
- status := logger.Logr().IsLevelEnabled(level)
- return status.Enabled
-}
-
-// zapToLogr converts Zap fields to Logr fields.
-// This will not be needed once Logr is used for all logging.
-func zapToLogr(zapFields []Field) logr.Fields {
- encoder := zapcore.NewMapObjectEncoder()
- for _, zapField := range zapFields {
- zapField.AddTo(encoder)
- }
- return logr.Fields(encoder.Fields)
-}
-
-// mlogLevelToLogrLevel converts a mlog logger level to
-// an array of discrete Logr levels.
-func mlogLevelToLogrLevels(level string) []LogLevel {
- levels := make([]LogLevel, 0)
- levels = append(levels, LvlError, LvlPanic, LvlFatal, LvlStdLog)
-
- switch level {
- case LevelDebug:
- levels = append(levels, LvlDebug)
- fallthrough
- case LevelInfo:
- levels = append(levels, LvlInfo)
- fallthrough
- case LevelWarn:
- levels = append(levels, LvlWarn)
- }
- return levels
-}
diff --git a/shared/mlog/mlog.go b/shared/mlog/mlog.go
new file mode 100644
index 0000000000..bfc2e5ab46
--- /dev/null
+++ b/shared/mlog/mlog.go
@@ -0,0 +1,407 @@
+// 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 = logr.Stringer
+
+// Err constructs a field containing a default key ("error") and error value.
+var Err = logr.Err
+
+// NamedErr constructs a field containing a key and error value.
+var NamedErr = logr.NamedErr
+
+// 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/shared/mlog/options.go b/shared/mlog/options.go
new file mode 100644
index 0000000000..3a98b480b7
--- /dev/null
+++ b/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/shared/mlog/stdlog.go b/shared/mlog/stdlog.go
deleted file mode 100644
index fd702abffa..0000000000
--- a/shared/mlog/stdlog.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "bytes"
- "strings"
-
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-// Implementation of zapcore.Core to interpret log messages from a standard logger
-// and translate the levels to zapcore levels.
-type stdLogLevelInterpreterCore struct {
- wrappedCore zapcore.Core
-}
-
-func stdLogInterpretZapEntry(entry zapcore.Entry) zapcore.Entry {
- message := entry.Message
- if strings.Index(message, "[DEBUG]") == 0 {
- entry.Level = zapcore.DebugLevel
- entry.Message = message[7:]
- } else if strings.Index(message, "[DEBG]") == 0 {
- entry.Level = zapcore.DebugLevel
- entry.Message = message[6:]
- } else if strings.Index(message, "[WARN]") == 0 {
- entry.Level = zapcore.WarnLevel
- entry.Message = message[6:]
- } else if strings.Index(message, "[ERROR]") == 0 {
- entry.Level = zapcore.ErrorLevel
- entry.Message = message[7:]
- } else if strings.Index(message, "[EROR]") == 0 {
- entry.Level = zapcore.ErrorLevel
- entry.Message = message[6:]
- } else if strings.Index(message, "[ERR]") == 0 {
- entry.Level = zapcore.ErrorLevel
- entry.Message = message[5:]
- } else if strings.Index(message, "[INFO]") == 0 {
- entry.Level = zapcore.InfoLevel
- entry.Message = message[6:]
- }
- return entry
-}
-
-func (s *stdLogLevelInterpreterCore) Enabled(lvl zapcore.Level) bool {
- return s.wrappedCore.Enabled(lvl)
-}
-
-func (s *stdLogLevelInterpreterCore) With(fields []zapcore.Field) zapcore.Core {
- return s.wrappedCore.With(fields)
-}
-
-func (s *stdLogLevelInterpreterCore) Check(entry zapcore.Entry, checkedEntry *zapcore.CheckedEntry) *zapcore.CheckedEntry {
- entry = stdLogInterpretZapEntry(entry)
- return s.wrappedCore.Check(entry, checkedEntry)
-}
-
-func (s *stdLogLevelInterpreterCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
- entry = stdLogInterpretZapEntry(entry)
- return s.wrappedCore.Write(entry, fields)
-}
-
-func (s *stdLogLevelInterpreterCore) Sync() error {
- return s.wrappedCore.Sync()
-}
-
-func getStdLogOption() zap.Option {
- return zap.WrapCore(
- func(core zapcore.Core) zapcore.Core {
- return &stdLogLevelInterpreterCore{core}
- },
- )
-}
-
-type loggerWriter struct {
- logFunc func(msg string, fields ...Field)
-}
-
-func (l *loggerWriter) Write(p []byte) (int, error) {
- trimmed := string(bytes.TrimSpace(p))
- for _, line := range strings.Split(trimmed, "\n") {
- l.logFunc(line)
- }
- return len(p), nil
-}
diff --git a/shared/mlog/stdlog_test.go b/shared/mlog/stdlog_test.go
deleted file mode 100644
index 139b5eab7f..0000000000
--- a/shared/mlog/stdlog_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
- "go.uber.org/zap/zapcore"
-)
-
-func TestStdLogInterpretZapEntry(t *testing.T) {
- for _, tc := range []struct {
- testname string
- message string
- expectedMessage string
- expectedLevel zapcore.Level
- }{
- {"Debug Basic", "[DEBUG]My message", "My message", zapcore.DebugLevel},
- {"Debug Basic2", "[DEBG]My message", "My message", zapcore.DebugLevel},
- {"Warn Basic", "[WARN]My message", "My message", zapcore.WarnLevel},
- {"Error Basic", "[ERROR]My message", "My message", zapcore.ErrorLevel},
- {"Error Basic2", "[EROR]My message", "My message", zapcore.ErrorLevel},
- {"Error Basic3", "[ERR]My message", "My message", zapcore.ErrorLevel},
- {"Info Basic", "[INFO]My message", "My message", zapcore.InfoLevel},
- {"Unknown level", "[UNKNOWN]My message", "[UNKNOWN]My message", zapcore.PanicLevel},
- {"No level", "My message", "My message", zapcore.PanicLevel},
- {"Empty message", "", "", zapcore.PanicLevel},
- {"Malformed level", "INFO]My message", "INFO]My message", zapcore.PanicLevel},
- } {
- t.Run(tc.testname, func(t *testing.T) {
- inEntry := zapcore.Entry{
- Level: zapcore.PanicLevel,
- Message: tc.message,
- }
- resultEntry := stdLogInterpretZapEntry(inEntry)
- assert.Equal(t, tc.expectedMessage, resultEntry.Message)
- assert.Equal(t, tc.expectedLevel, resultEntry.Level)
- })
- }
-}
diff --git a/shared/mlog/sugar.go b/shared/mlog/sugar.go
deleted file mode 100644
index 2368b085b7..0000000000
--- a/shared/mlog/sugar.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "go.uber.org/zap"
-)
-
-// Made for the plugin interface, use the regular logger for other uses
-type SugarLogger struct {
- wrappedLogger *Logger
- zapSugar *zap.SugaredLogger
-}
-
-func (l *SugarLogger) Debug(msg string, keyValuePairs ...interface{}) {
- l.zapSugar.Debugw(msg, keyValuePairs...)
-}
-
-func (l *SugarLogger) Info(msg string, keyValuePairs ...interface{}) {
- l.zapSugar.Infow(msg, keyValuePairs...)
-}
-
-func (l *SugarLogger) Error(msg string, keyValuePairs ...interface{}) {
- l.zapSugar.Errorw(msg, keyValuePairs...)
-}
-
-func (l *SugarLogger) Warn(msg string, keyValuePairs ...interface{}) {
- l.zapSugar.Warnw(msg, keyValuePairs...)
-}
diff --git a/shared/mlog/syslog.go b/shared/mlog/syslog.go
deleted file mode 100644
index 8766a96476..0000000000
--- a/shared/mlog/syslog.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "context"
- "crypto/tls"
- "crypto/x509"
- "encoding/base64"
- "errors"
- "fmt"
- "io/ioutil"
-
- "github.com/mattermost/logr"
- "github.com/wiggin77/merror"
- syslog "github.com/wiggin77/srslog"
-)
-
-// Syslog outputs log records to local or remote syslog.
-type Syslog struct {
- logr.Basic
- w *syslog.Writer
-}
-
-// SyslogParams provides parameters for dialing a syslog daemon.
-type SyslogParams struct {
- IP string `json:"IP"`
- Port int `json:"Port"`
- Tag string `json:"Tag"`
- TLS bool `json:"TLS"`
- Cert string `json:"Cert"`
- Insecure bool `json:"Insecure"`
-}
-
-// NewSyslogTarget creates a target capable of outputting log records to remote or local syslog, with or without TLS.
-func NewSyslogTarget(filter logr.Filter, formatter logr.Formatter, params *SyslogParams, maxQueue int) (*Syslog, error) {
- network := "tcp"
- var config *tls.Config
-
- if params.TLS {
- network = "tcp+tls"
- config = &tls.Config{InsecureSkipVerify: params.Insecure}
- if params.Cert != "" {
- pool, err := getCertPool(params.Cert)
- if err != nil {
- return nil, err
- }
- config.RootCAs = pool
- }
- }
- raddr := fmt.Sprintf("%s:%d", params.IP, params.Port)
-
- writer, err := syslog.DialWithTLSConfig(network, raddr, syslog.LOG_INFO, params.Tag, config)
- if err != nil {
- return nil, err
- }
-
- s := &Syslog{w: writer}
- s.Basic.Start(s, s, filter, formatter, maxQueue)
-
- return s, nil
-}
-
-// Shutdown stops processing log records after making best effort to flush queue.
-func (s *Syslog) Shutdown(ctx context.Context) error {
- errs := merror.New()
-
- err := s.Basic.Shutdown(ctx)
- errs.Append(err)
-
- err = s.w.Close()
- errs.Append(err)
-
- return errs.ErrorOrNil()
-}
-
-// getCertPool returns a x509.CertPool containing the cert(s)
-// from `cert`, which can be a path to a .pem or .crt file,
-// or a base64 encoded cert.
-func getCertPool(cert string) (*x509.CertPool, error) {
- if cert == "" {
- return nil, errors.New("no cert provided")
- }
-
- // first treat as a file and try to read.
- serverCert, err := ioutil.ReadFile(cert)
- if err != nil {
- // maybe it's a base64 encoded cert
- serverCert, err = base64.StdEncoding.DecodeString(cert)
- if err != nil {
- return nil, errors.New("cert cannot be read")
- }
- }
-
- pool := x509.NewCertPool()
- if ok := pool.AppendCertsFromPEM(serverCert); ok {
- return pool, nil
- }
- return nil, errors.New("cannot parse cert")
-}
-
-// Write converts the log record to bytes, via the Formatter,
-// and outputs to syslog.
-func (s *Syslog) Write(rec *logr.LogRec) error {
- _, stacktrace := s.IsLevelEnabled(rec.Level())
-
- buf := rec.Logger().Logr().BorrowBuffer()
- defer rec.Logger().Logr().ReleaseBuffer(buf)
-
- buf, err := s.Formatter().Format(rec, stacktrace, buf)
- if err != nil {
- return err
- }
- txt := buf.String()
-
- switch rec.Level() {
- case logr.Panic, logr.Fatal:
- err = s.w.Crit(txt)
- case logr.Error:
- err = s.w.Err(txt)
- case logr.Warn:
- err = s.w.Warning(txt)
- case logr.Debug, logr.Trace:
- err = s.w.Debug(txt)
- default:
- // logr.Info plus all custom levels.
- err = s.w.Info(txt)
- }
-
- if err != nil {
- reporter := rec.Logger().Logr().ReportError
- reporter(fmt.Errorf("syslog write fail: %w", err))
- // syslog writer will try to reconnect.
- }
- return err
-}
-
-// String returns a string representation of this target.
-func (s *Syslog) String() string {
- return "SyslogTarget"
-}
diff --git a/shared/mlog/syslog_test.go b/shared/mlog/syslog_test.go
deleted file mode 100644
index d60bdc0721..0000000000
--- a/shared/mlog/syslog_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func Test_getCertPool(t *testing.T) {
- tests := []struct {
- name string
- cert string
- wantErr bool
- }{
- {name: "garbage in, garbage out", wantErr: true, cert: "THISISNOTACERT"},
- {name: "good cert base64", wantErr: false, cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURqekNDQW5lZ0F3SUJBZ0lSQVBZZlJTd2R6S29wQkt4WXhLcXNsSlV3RFFZSktvWklodmNOQVFFTEJRQXcKSnpFbE1DTUdBMVVFQXd3Y1RXRjBkR1Z5Ylc5emRDd2dTVzVqTGlCSmJuUmxjbTVoYkNCRFFUQWVGdzB4T1RBegpNakl3TURFME1UVmFGdzB5TWpBek1EWXdNREUwTVRWYU1Ec3hPVEEzQmdOVkJBTVRNRTFoZEhSbGNtMXZjM1FzCklFbHVZeTRnU1c1MFpYSnVZV3dnU1c1MFpYSnRaV1JwWVhSbElFRjFkR2h2Y21sMGVUQ0NBU0l3RFFZSktvWkkKaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNamxpUmRtdm5OTDR1L0pyL00yZFB3UW1USlhFQlkvVnE5UQp2QVU1MlgzdFJNQ1B4Y2FGeit4NmZ0dXZkTzJOZG9oWEdBbXR4OVFVNUxaY3ZGZVREcG9WRUJvOUErNGp0THZECkRaWWFUTkxwSm1vU29KSGFEYmRXWCtPQU9xeURpV1M3NDFMdWlNS1dIaGV3OVFPaXNhdDJaSU5QeGptQWQ5d0UKeHRoVE1nenN2N01VcW5NZXI4VTVPR1EwUXk3d0FtTlJjKzJLM3FQd2t4ZTJSVXZjdGU1MERVRk5neEVnaW5zaAp2cmtPWFIzODN2VUNaZnU3MnF1OG9nZ2ppUXB5VGxsdTVqZTJBcDZKTGpZTGtFTWlNcXJZQUR1V29yL1pId2E2CldyRnFWRVR4V2ZBVjV1OUVoMHdaTS9LS1l3UlF1dzl5K05hbnM3N0ZtVWwxdFZXV05OOENBd0VBQWFPQm9UQ0IKbmpBTUJnTlZIUk1FQlRBREFRSC9NQjBHQTFVZERnUVdCQlFZNFVxc3d5cjJoTy9IZXRadDJSRHhKZFRJUGpCaQpCZ05WSFNNRVd6QlpnQlJGWlhWZzJaNXROSXNXZVdqQkxFeTJ5ektiTUtFcnBDa3dKekVsTUNNR0ExVUVBd3djClRXRjBkR1Z5Ylc5emRDd2dTVzVqTGlCSmJuUmxjbTVoYkNCRFFZSVVFaWZHVU9NK2JJRlpvMXRralpCNVlHQnIKMHhFd0N3WURWUjBQQkFRREFnRUdNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFFZGV4TDMwUTB6QkhtUEFIOApMaGRLN2RielcxQ21JTGJ4UlpsS0F3Uk4raEtSWGlNVzNNSElraE51b1Y5QWV2NjAyUStqYTRsV3NSaS9rdE9MCm5pMUZXeDVnU1NjZ2RHOEpHajQ3ZE9tb1QzdlhLWDcrdW1pdjRyUUxQRGw5L0RLTXV2MjA0T1lKcTZWVCt1TlUKNkM2a0wxNTdqR0pFTzc2SDRmTVo4b1lzRDdTcTB6amlOS3R1Q1lpaTBuZ0gzajNnQjFqQUNMcVJndmVVN01kVApwcU9WMktmWTMxK2g4VkJ0a1V2bGpOenRROXhOWThGam10MFNNZjdFM0ZhVWNhYXIzWkNyNzBHNWFVM2RLYmU3CjQ3dkdPQmE1dENxdzRZSzBqZ0RLaWQzSUpRdWw5YTNKMW1Tc0g4V3kzdG85Y0FWNEtHWkJRTG56Q1gxNWEvK3YKM3lWaAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tIAotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJRGZqQ0NBbWFnQXdJQkFnSVVFaWZHVU9NK2JJRlpvMXRralpCNVlHQnIweEV3RFFZSktvWklodmNOQVFFTApCUUF3SnpFbE1DTUdBMVVFQXd3Y1RXRjBkR1Z5Ylc5emRDd2dTVzVqTGlCSmJuUmxjbTVoYkNCRFFUQWVGdzB4Ck9UQXpNakV5TVRJNE5ETmFGdzB5T1RBek1UZ3lNVEk0TkROYU1DY3hKVEFqQmdOVkJBTU1IRTFoZEhSbGNtMXYKYzNRc0lFbHVZeTRnU1c1MFpYSnVZV3dnUTBFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFSwpBb0lCQVFESDBYcTVyTUJHcEtPVldUcGI1TW5hSklXRlAvdk90dkVrKzdoVnJmT2ZlMS81eDBLazNVZ0FIajg1Cm90YUVaRDFMaG4vSkxrRXFDaUUvVVhNSkZ3SkRsTmNPNENrZEtCU3BZWDRiS0FxeTVxL1gzUXdpb01TTnBKRzEKK1lZck5HQkgwc2dLY0tqeUNhTGhtcVlMRDB4WkRWT21XSVlCVTlqVVB5WHc1VTB0bnNWclRxR014VmttMXhDWQprckNXTjFab1VyTHZMME1DWmM1cXB4b1BUb3ByOVVPOWNxU0JTdXk2QlZXVnVFV0JaaHBxSHQrdWw4VnhoenpZCnExazRsN3IycXcrL3dtMWlKQmVkVGVCVmVXTmFnOEphVmZMZ3UrL1c3b0pWbFBPMzJQbzdwbnZIcDhpSjNiNEsKelh5VkhhVFg0UzZFbSs2TFY4ODU1VFlyU2h6bEFnTUJBQUdqZ2FFd2daNHdIUVlEVlIwT0JCWUVGRVZsZFdEWgpubTAwaXhaNWFNRXNUTGJMTXBzd01HSUdBMVVkSXdSYk1GbUFGRVZsZFdEWm5tMDBpeFo1YU1Fc1RMYkxNcHN3Cm9TdWtLVEFuTVNVd0l3WURWUVFEREJ4TllYUjBaWEp0YjNOMExDQkpibU11SUVsdWRHVnlibUZzSUVOQmdoUVMKSjhaUTR6NXNnVm1qVzJTTmtIbGdZR3ZURVRBTUJnTlZIUk1FQlRBREFRSC9NQXNHQTFVZER3UUVBd0lCQmpBTgpCZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFQaUNXRm1vcHlBa1kyVDNaeW80eWFSUGhYMStWT1RNS0p0WTZFVWhxCi9HSHo2a3pFeXZDVUJmME44OTJjaWJHeGVrckVvSXRZOU5xTzZSUVJmb3dnK0duNWtjMTN6NE55TDJXOC9lb1QKWHkwWnZmYVFiVSsrZlE2cFZ0V3RNYmxETVU5eGlZZDcvTUR2SnBPMzI4bDFWaGNkcDhrRWkrbEN2cHkwc0NSYwpQeHpQaGJnQ01BYlpFR3grNFRNUWQ0U1pLemxSeFcvMmZmbHBSZWg2djFEdjBWRFVTWVFXd3NVbmFMcGRLSGZoCmE1azB2dXlTWWNzekU0WUtsWTB6YWtlRmxKZnA3ZkJwMXhUd2NkVzhhVGZ3MTVFaWNQTXdUYzZ4eEE0SkpVSngKY2RkdTgxN24xbmF5SzV1NnI5UWgxb0lWa3IwbkM5WUVMTU15NGRwUGdKODhTQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"},
- {name: "good cert file", wantErr: false, cert: "test-tls-client-cert.pem"},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- pool, err := getCertPool(tt.cert)
- if tt.wantErr {
- assert.Error(t, err)
- assert.Nil(t, pool)
- } else {
- assert.NoError(t, err)
- assert.NotNil(t, pool)
-
- // Test PEM has 2 certs.
- subjects := pool.Subjects()
- assert.Len(t, subjects, 2)
- }
- })
- }
-}
diff --git a/shared/mlog/tcp_test.go b/shared/mlog/tcp_test.go
deleted file mode 100644
index 99fe2274f7..0000000000
--- a/shared/mlog/tcp_test.go
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "net"
- "sync"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
- "github.com/wiggin77/merror"
-)
-
-const (
- testPort = 18066
-)
-
-func TestNewTCPTarget(t *testing.T) {
- target := LogTarget{
- Type: "tcp",
- Format: "json",
- Levels: []LogLevel{LvlInfo},
- Options: []byte(`{"IP": "localhost", "Port": 18066}`),
- MaxQueueSize: 1000,
- }
- targets := map[string]*LogTarget{"tcp_test": &target}
-
- t.Run("logging", func(t *testing.T) {
- buf := &buffer{}
- server, err := newSocketServer(testPort, buf)
- require.NoError(t, err)
-
- data := []string{"I drink your milkshake!", "We don't need no badges!", "You can't fight in here! This is the war room!"}
-
- logger := newLogr()
- err = logrAddTargets(logger, targets)
- require.NoError(t, err)
-
- for _, s := range data {
- logger.Info(s)
- }
- err = logger.Logr().Flush()
- require.NoError(t, err)
- err = logger.Logr().Shutdown()
- require.NoError(t, err)
-
- err = server.waitForAnyConnection()
- require.NoError(t, err)
-
- err = server.stopServer(true)
- require.NoError(t, err)
-
- sdata := buf.String()
- for _, s := range data {
- require.Contains(t, sdata, s)
- }
- })
-}
-
-// socketServer is a simple socket server used for testing TCP log targets.
-// Note: There is more synchronization here than normally needed to avoid flaky tests.
-// For example, it's possible for a unit test to create a socketServer, attempt
-// writing to it, and stop the socket server before "go ss.listen()" gets scheduled.
-type socketServer struct {
- listener net.Listener
- anyConn chan struct{}
- buf *buffer
- conns map[string]*socketServerConn
- mux sync.Mutex
-}
-
-type socketServerConn struct {
- raddy string
- conn net.Conn
- done chan struct{}
-}
-
-func newSocketServer(port int, buf *buffer) (*socketServer, error) {
- ss := &socketServer{
- buf: buf,
- conns: make(map[string]*socketServerConn),
- anyConn: make(chan struct{}),
- }
-
- addy := fmt.Sprintf(":%d", port)
- l, err := net.Listen("tcp4", addy)
- if err != nil {
- return nil, err
- }
- ss.listener = l
-
- go ss.listen()
- return ss, nil
-}
-
-func (ss *socketServer) listen() {
- for {
- conn, err := ss.listener.Accept()
- if err != nil {
- return
- }
- sconn := &socketServerConn{raddy: conn.RemoteAddr().String(), conn: conn, done: make(chan struct{})}
- ss.registerConnection(sconn)
- go ss.handleConnection(sconn)
- }
-}
-
-func (ss *socketServer) waitForAnyConnection() error {
- var err error
- select {
- case <-ss.anyConn:
- case <-time.After(5 * time.Second):
- err = errors.New("wait for any connection timed out")
- }
- return err
-}
-
-func (ss *socketServer) handleConnection(sconn *socketServerConn) {
- close(ss.anyConn)
- defer ss.unregisterConnection(sconn)
- buf := make([]byte, 1024)
-
- for {
- n, err := sconn.conn.Read(buf)
- if n > 0 {
- ss.buf.Write(buf[:n])
- }
- if err == io.EOF {
- ss.signalDone(sconn)
- return
- }
- }
-}
-
-func (ss *socketServer) registerConnection(sconn *socketServerConn) {
- ss.mux.Lock()
- defer ss.mux.Unlock()
- ss.conns[sconn.raddy] = sconn
-}
-
-func (ss *socketServer) unregisterConnection(sconn *socketServerConn) {
- ss.mux.Lock()
- defer ss.mux.Unlock()
- delete(ss.conns, sconn.raddy)
-}
-
-func (ss *socketServer) signalDone(sconn *socketServerConn) {
- ss.mux.Lock()
- defer ss.mux.Unlock()
- close(sconn.done)
-}
-
-func (ss *socketServer) stopServer(wait bool) error {
- errs := merror.New()
- ss.listener.Close()
-
- ss.mux.Lock()
- // defensive copy; no more connections can be accepted so copy will stay current.
- conns := make(map[string]*socketServerConn, len(ss.conns))
- for k, v := range ss.conns {
- conns[k] = v
- }
- ss.mux.Unlock()
-
- for _, sconn := range conns {
- if wait {
- select {
- case <-sconn.done:
- case <-time.After(time.Second * 5):
- errs.Append(errors.New("timed out"))
- }
- }
- }
- return errs.ErrorOrNil()
-}
-
-type buffer struct {
- buf bytes.Buffer
- mux sync.Mutex
-}
-
-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()
-}
diff --git a/shared/mlog/testing.go b/shared/mlog/testing.go
deleted file mode 100644
index 6b41a7e4fb..0000000000
--- a/shared/mlog/testing.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package mlog
-
-import (
- "io"
- "strings"
- "sync"
- "testing"
-
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-// testingWriter is an io.Writer that writes through t.Log
-type testingWriter struct {
- tb testing.TB
-}
-
-func (tw *testingWriter) Write(b []byte) (int, error) {
- tw.tb.Log(strings.TrimSpace(string(b)))
- return len(b), nil
-}
-
-// NewTestingLogger creates a Logger that proxies logs through a testing interface.
-// This allows tests that spin up App instances to avoid spewing logs unless the test fails or -verbose is specified.
-func NewTestingLogger(tb testing.TB, writer io.Writer) *Logger {
- logWriter := &testingWriter{tb}
- multiWriter := io.MultiWriter(logWriter, writer)
- logWriterSync := zapcore.AddSync(multiWriter)
-
- testingLogger := &Logger{
- consoleLevel: zap.NewAtomicLevelAt(getZapLevel("debug")),
- fileLevel: zap.NewAtomicLevelAt(getZapLevel("info")),
- logrLogger: newLogr(),
- mutex: &sync.RWMutex{},
- }
-
- logWriterCore := zapcore.NewCore(makeEncoder(true, false), zapcore.Lock(logWriterSync), testingLogger.consoleLevel)
-
- testingLogger.zap = zap.New(logWriterCore,
- zap.AddCaller(),
- )
- return testingLogger
-}
diff --git a/shared/mlog/tlog.go b/shared/mlog/tlog.go
new file mode 100644
index 0000000000..89efe303cd
--- /dev/null
+++ b/shared/mlog/tlog.go
@@ -0,0 +1,141 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package mlog
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "strings"
+ "sync"
+ "testing"
+
+ "github.com/mattermost/logr/v2"
+ "github.com/mattermost/logr/v2/formatters"
+ "github.com/mattermost/logr/v2/targets"
+)
+
+// CreateTestLogger creates a logger for unit tests, using the `TB.Log`
+func CreateTestLogger(tb testing.TB, writer io.Writer, levels ...Level) *Logger {
+ logger, _ := NewLogger()
+
+ filter := logr.NewCustomFilter(levels...)
+ formatter := &formatters.Plain{}
+
+ if tb != nil {
+ testtarget := newTestingTarget(tb)
+ if err := logger.log.Logr().AddTarget(testtarget, "_testTB", filter, formatter, 1000); err != nil {
+ tb.Fail()
+ return nil
+ }
+ }
+
+ if writer != nil {
+ target := targets.NewWriterTarget(writer)
+ if err := logger.log.Logr().AddTarget(target, "_testWriter", filter, formatter, 1000); err != nil {
+ tb.Fail()
+ return nil
+ }
+ }
+ return logger
+}
+
+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
+}
+
+// testingTarget is a simple log target that writes to the testing log.
+type testingTarget struct {
+ mux sync.Mutex
+ tb testing.TB
+}
+
+func newTestingTarget(tb testing.TB) *testingTarget {
+ return &testingTarget{
+ tb: tb,
+ }
+}
+
+// Init is called once to initialize the target.
+func (tt *testingTarget) Init() error {
+ return nil
+}
+
+// Write outputs bytes to this file target.
+func (tt *testingTarget) Write(p []byte, rec *logr.LogRec) (int, error) {
+ tt.mux.Lock()
+ defer tt.mux.Unlock()
+
+ if tt.tb != nil {
+ tt.tb.Helper()
+ tt.tb.Log(strings.TrimSpace(string(p)))
+ }
+ return len(p), nil
+}
+
+// Shutdown is called once to free/close any resources.
+// Target queue is already drained when this is called.
+func (tt *testingTarget) Shutdown() error {
+ tt.mux.Lock()
+ defer tt.mux.Unlock()
+
+ tt.tb = nil
+ return nil
+}
+
+// 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()
+}
diff --git a/store/localcachelayer/main_test.go b/store/localcachelayer/main_test.go
index d492bb3f92..ed82cb3d44 100644
--- a/store/localcachelayer/main_test.go
+++ b/store/localcachelayer/main_test.go
@@ -13,7 +13,6 @@ import (
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/cache"
cachemocks "github.com/mattermost/mattermost-server/v6/services/cache/mocks"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
"github.com/mattermost/mattermost-server/v6/store/sqlstore"
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
@@ -172,7 +171,6 @@ func getMockStore() *mocks.Store {
}
func TestMain(m *testing.M) {
- mlog.DisableZap()
mainHelper = testlib.NewMainHelperWithOptions(nil)
defer mainHelper.Close()
diff --git a/store/sqlstore/main_test.go b/store/sqlstore/main_test.go
index a47adda458..fe6b4c386a 100644
--- a/store/sqlstore/main_test.go
+++ b/store/sqlstore/main_test.go
@@ -6,7 +6,6 @@ package sqlstore_test
import (
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store/sqlstore"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -14,7 +13,6 @@ import (
var mainHelper *testlib.MainHelper
func TestMain(m *testing.M) {
- mlog.DisableZap()
mainHelper = testlib.NewMainHelperWithOptions(nil)
defer mainHelper.Close()
diff --git a/testlib/assertions.go b/testlib/assertions.go
index cb2ab5ce30..5b6afd7a97 100644
--- a/testlib/assertions.go
+++ b/testlib/assertions.go
@@ -4,14 +4,13 @@
package testlib
import (
- "bytes"
"encoding/json"
"io"
"testing"
)
// AssertLog asserts that a JSON-encoded buffer of logs contains one with the given level and message.
-func AssertLog(t *testing.T, logs *bytes.Buffer, level, message string) {
+func AssertLog(t *testing.T, logs io.Reader, level, message string) {
dec := json.NewDecoder(logs)
for {
var log struct {
@@ -33,7 +32,7 @@ func AssertLog(t *testing.T, logs *bytes.Buffer, level, message string) {
}
// AssertNoLog asserts that a JSON-encoded buffer of logs does not contains one with the given level and message.
-func AssertNoLog(t *testing.T, logs *bytes.Buffer, level, message string) {
+func AssertNoLog(t *testing.T, logs io.Reader, level, message string) {
dec := json.NewDecoder(logs)
for {
var log struct {
diff --git a/testlib/helper.go b/testlib/helper.go
index c8d53ace46..31c7b279c8 100644
--- a/testlib/helper.go
+++ b/testlib/helper.go
@@ -16,7 +16,6 @@ import (
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/searchengine"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
"github.com/mattermost/mattermost-server/v6/store/searchlayer"
"github.com/mattermost/mattermost-server/v6/store/sqlstore"
@@ -53,16 +52,6 @@ func NewMainHelperWithOptions(options *HelperOptions) *MainHelper {
var mainHelper MainHelper
flag.Parse()
- // Setup a global logger to catch tests logging outside of app context
- // The global logger will be stomped by apps initializing but that's fine for testing.
- // Ideally this won't happen.
- mlog.InitGlobalLogger(mlog.NewLogger(&mlog.LoggerConfiguration{
- EnableConsole: true,
- ConsoleJson: true,
- ConsoleLevel: "error",
- EnableFile: false,
- }))
-
utils.TranslationsPreInit()
if options != nil {
diff --git a/utils/logger.go b/utils/logger.go
deleted file mode 100644
index 0de3fdb240..0000000000
--- a/utils/logger.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-package utils
-
-import (
- "path/filepath"
- "strings"
-
- "github.com/mattermost/mattermost-server/v6/model"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
- "github.com/mattermost/mattermost-server/v6/utils/fileutils"
-)
-
-const (
- LogRotateSize = 10000
- LogFilename = "mattermost.log"
- LogNotificationFilename = "notifications.log"
-)
-
-type fileLocationFunc func(string) string
-
-func MloggerConfigFromLoggerConfig(s *model.LogSettings, getFileFunc fileLocationFunc) *mlog.LoggerConfiguration {
- return &mlog.LoggerConfiguration{
- EnableConsole: *s.EnableConsole,
- ConsoleJson: *s.ConsoleJson,
- ConsoleLevel: strings.ToLower(*s.ConsoleLevel),
- EnableFile: *s.EnableFile,
- FileJson: *s.FileJson,
- FileLevel: strings.ToLower(*s.FileLevel),
- FileLocation: getFileFunc(*s.FileLocation),
- EnableColor: *s.EnableColor,
- }
-}
-
-func GetLogFileLocation(fileLocation string) string {
- if fileLocation == "" {
- fileLocation, _ = fileutils.FindDir("logs")
- }
-
- return filepath.Join(fileLocation, LogFilename)
-}
-
-func GetNotificationsLogFileLocation(fileLocation string) string {
- if fileLocation == "" {
- fileLocation, _ = fileutils.FindDir("logs")
- }
-
- return filepath.Join(fileLocation, LogNotificationFilename)
-}
-
-func GetLogSettingsFromNotificationsLogSettings(notificationLogSettings *model.NotificationLogSettings) *model.LogSettings {
- return &model.LogSettings{
- ConsoleJson: notificationLogSettings.ConsoleJson,
- ConsoleLevel: notificationLogSettings.ConsoleLevel,
- EnableConsole: notificationLogSettings.EnableConsole,
- EnableFile: notificationLogSettings.EnableFile,
- FileJson: notificationLogSettings.FileJson,
- FileLevel: notificationLogSettings.FileLevel,
- FileLocation: notificationLogSettings.FileLocation,
- AdvancedLoggingConfig: notificationLogSettings.AdvancedLoggingConfig,
- EnableColor: notificationLogSettings.EnableColor,
- }
-}
-
-// DON'T USE THIS Modify the level on the app logger
-func DisableDebugLogForTest() {
- mlog.GloballyDisableDebugLogForTest()
-}
-
-// DON'T USE THIS Modify the level on the app logger
-func EnableDebugLogForTest() {
- mlog.GloballyEnableDebugLogForTest()
-}
diff --git a/vendor/github.com/mattermost/logr/config.go b/vendor/github.com/mattermost/logr/config.go
deleted file mode 100644
index 83d4b0c1c1..0000000000
--- a/vendor/github.com/mattermost/logr/config.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package logr
-
-import (
- "fmt"
-
- "github.com/wiggin77/cfg"
-)
-
-func ConfigLogger(config *cfg.Config) error {
- return fmt.Errorf("Not implemented yet")
-}
diff --git a/vendor/github.com/mattermost/logr/filter.go b/vendor/github.com/mattermost/logr/filter.go
deleted file mode 100644
index 6e654cd7b2..0000000000
--- a/vendor/github.com/mattermost/logr/filter.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package logr
-
-// LevelID is the unique id of each level.
-type LevelID uint
-
-// Level provides a mechanism to enable/disable specific log lines.
-type Level struct {
- ID LevelID
- Name string
- Stacktrace bool
-}
-
-// String returns the name of this level.
-func (level Level) String() string {
- return level.Name
-}
-
-// Filter allows targets to determine which Level(s) are active
-// for logging and which Level(s) require a stack trace to be output.
-// A default implementation using "panic, fatal..." is provided, and
-// a more flexible alternative implementation is also provided that
-// allows any number of custom levels.
-type Filter interface {
- IsEnabled(Level) bool
- IsStacktraceEnabled(Level) bool
-}
diff --git a/vendor/github.com/mattermost/logr/format/json.go b/vendor/github.com/mattermost/logr/format/json.go
deleted file mode 100644
index 8f56c6cb38..0000000000
--- a/vendor/github.com/mattermost/logr/format/json.go
+++ /dev/null
@@ -1,273 +0,0 @@
-package format
-
-import (
- "bytes"
- "fmt"
- "runtime"
- "sort"
- "sync"
- "time"
-
- "github.com/francoispqt/gojay"
- "github.com/mattermost/logr"
-)
-
-// ContextField is a name/value pair within the context fields.
-type ContextField struct {
- Key string
- Val interface{}
-}
-
-// JSON formats log records as JSON.
-type JSON struct {
- // DisableTimestamp disables output of timestamp field.
- DisableTimestamp bool
- // DisableLevel disables output of level field.
- DisableLevel bool
- // DisableMsg disables output of msg field.
- DisableMsg bool
- // DisableContext disables output of all context fields.
- DisableContext bool
- // DisableStacktrace disables output of stack trace.
- DisableStacktrace bool
-
- // TimestampFormat is an optional format for timestamps. If empty
- // then DefTimestampFormat is used.
- TimestampFormat string
-
- // Deprecated: this has no effect.
- Indent string
-
- // EscapeHTML determines if certain characters (e.g. `<`, `>`, `&`)
- // are escaped.
- EscapeHTML bool
-
- // KeyTimestamp overrides the timestamp field key name.
- KeyTimestamp string
-
- // KeyLevel overrides the level field key name.
- KeyLevel string
-
- // KeyMsg overrides the msg field key name.
- KeyMsg string
-
- // KeyContextFields when not empty will group all context fields
- // under this key.
- KeyContextFields string
-
- // KeyStacktrace overrides the stacktrace field key name.
- KeyStacktrace string
-
- // ContextSorter allows custom sorting for the context fields.
- ContextSorter func(fields logr.Fields) []ContextField
-
- once sync.Once
-}
-
-// Format converts a log record to bytes in JSON format.
-func (j *JSON) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
- j.once.Do(j.applyDefaultKeyNames)
-
- if buf == nil {
- buf = &bytes.Buffer{}
- }
- enc := gojay.BorrowEncoder(buf)
- defer func() {
- enc.Release()
- }()
-
- sorter := j.ContextSorter
- if sorter == nil {
- sorter = j.defaultContextSorter
- }
-
- jlr := JSONLogRec{
- LogRec: rec,
- JSON: j,
- stacktrace: stacktrace,
- sorter: sorter,
- }
-
- err := enc.EncodeObject(jlr)
- if err != nil {
- return nil, err
- }
- buf.WriteByte('\n')
- return buf, nil
-}
-
-func (j *JSON) applyDefaultKeyNames() {
- if j.KeyTimestamp == "" {
- j.KeyTimestamp = "timestamp"
- }
- if j.KeyLevel == "" {
- j.KeyLevel = "level"
- }
- if j.KeyMsg == "" {
- j.KeyMsg = "msg"
- }
- if j.KeyStacktrace == "" {
- j.KeyStacktrace = "stacktrace"
- }
-}
-
-// defaultContextSorter sorts the context fields alphabetically by key.
-func (j *JSON) defaultContextSorter(fields logr.Fields) []ContextField {
- keys := make([]string, 0, len(fields))
- for k := range fields {
- keys = append(keys, k)
- }
- sort.Strings(keys)
-
- cf := make([]ContextField, 0, len(keys))
- for _, k := range keys {
- cf = append(cf, ContextField{Key: k, Val: fields[k]})
- }
- return cf
-}
-
-// JSONLogRec decorates a LogRec adding JSON encoding.
-type JSONLogRec struct {
- *logr.LogRec
- *JSON
- stacktrace bool
- sorter func(fields logr.Fields) []ContextField
-}
-
-// MarshalJSONObject encodes the LogRec as JSON.
-func (rec JSONLogRec) MarshalJSONObject(enc *gojay.Encoder) {
- if !rec.DisableTimestamp {
- timestampFmt := rec.TimestampFormat
- if timestampFmt == "" {
- timestampFmt = logr.DefTimestampFormat
- }
- time := rec.Time()
- enc.AddTimeKey(rec.KeyTimestamp, &time, timestampFmt)
- }
- if !rec.DisableLevel {
- enc.AddStringKey(rec.KeyLevel, rec.Level().Name)
- }
- if !rec.DisableMsg {
- enc.AddStringKey(rec.KeyMsg, rec.Msg())
- }
- if !rec.DisableContext {
- ctxFields := rec.sorter(rec.Fields())
- if rec.KeyContextFields != "" {
- enc.AddObjectKey(rec.KeyContextFields, jsonFields(ctxFields))
- } else {
- if len(ctxFields) > 0 {
- for _, cf := range ctxFields {
- key := rec.prefixCollision(cf.Key)
- encodeField(enc, key, cf.Val)
- }
- }
- }
- }
- if rec.stacktrace && !rec.DisableStacktrace {
- frames := rec.StackFrames()
- if len(frames) > 0 {
- enc.AddArrayKey(rec.KeyStacktrace, stackFrames(frames))
- }
- }
-
-}
-
-// IsNil returns true if the LogRec pointer is nil.
-func (rec JSONLogRec) IsNil() bool {
- return rec.LogRec == nil
-}
-
-func (rec JSONLogRec) prefixCollision(key string) string {
- switch key {
- case rec.KeyTimestamp, rec.KeyLevel, rec.KeyMsg, rec.KeyStacktrace:
- return rec.prefixCollision("_" + key)
- }
- return key
-}
-
-type stackFrames []runtime.Frame
-
-// MarshalJSONArray encodes stackFrames slice as JSON.
-func (s stackFrames) MarshalJSONArray(enc *gojay.Encoder) {
- for _, frame := range s {
- enc.AddObject(stackFrame(frame))
- }
-}
-
-// IsNil returns true if stackFrames is empty slice.
-func (s stackFrames) IsNil() bool {
- return len(s) == 0
-}
-
-type stackFrame runtime.Frame
-
-// MarshalJSONArray encodes stackFrame as JSON.
-func (f stackFrame) MarshalJSONObject(enc *gojay.Encoder) {
- enc.AddStringKey("Function", f.Function)
- enc.AddStringKey("File", f.File)
- enc.AddIntKey("Line", f.Line)
-}
-
-func (f stackFrame) IsNil() bool {
- return false
-}
-
-type jsonFields []ContextField
-
-// MarshalJSONObject encodes Fields map to JSON.
-func (f jsonFields) MarshalJSONObject(enc *gojay.Encoder) {
- for _, ctxField := range f {
- encodeField(enc, ctxField.Key, ctxField.Val)
- }
-}
-
-// IsNil returns true if map is nil.
-func (f jsonFields) IsNil() bool {
- return f == nil
-}
-
-func encodeField(enc *gojay.Encoder, key string, val interface{}) {
- switch vt := val.(type) {
- case gojay.MarshalerJSONObject:
- enc.AddObjectKey(key, vt)
- case gojay.MarshalerJSONArray:
- enc.AddArrayKey(key, vt)
- case string:
- enc.AddStringKey(key, vt)
- case error:
- enc.AddStringKey(key, vt.Error())
- case bool:
- enc.AddBoolKey(key, vt)
- case int:
- enc.AddIntKey(key, vt)
- case int64:
- enc.AddInt64Key(key, vt)
- case int32:
- enc.AddIntKey(key, int(vt))
- case int16:
- enc.AddIntKey(key, int(vt))
- case int8:
- enc.AddIntKey(key, int(vt))
- case uint64:
- enc.AddIntKey(key, int(vt))
- case uint32:
- enc.AddIntKey(key, int(vt))
- case uint16:
- enc.AddIntKey(key, int(vt))
- case uint8:
- enc.AddIntKey(key, int(vt))
- case float64:
- enc.AddFloatKey(key, vt)
- case float32:
- enc.AddFloat32Key(key, vt)
- case *gojay.EmbeddedJSON:
- enc.AddEmbeddedJSONKey(key, vt)
- case time.Time:
- enc.AddTimeKey(key, &vt, logr.DefTimestampFormat)
- case *time.Time:
- enc.AddTimeKey(key, vt, logr.DefTimestampFormat)
- default:
- s := fmt.Sprintf("%v", vt)
- enc.AddStringKey(key, s)
- }
-}
diff --git a/vendor/github.com/mattermost/logr/format/plain.go b/vendor/github.com/mattermost/logr/format/plain.go
deleted file mode 100644
index 3fa92b4900..0000000000
--- a/vendor/github.com/mattermost/logr/format/plain.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package format
-
-import (
- "bytes"
- "fmt"
-
- "github.com/mattermost/logr"
-)
-
-// Plain is the simplest formatter, outputting only text with
-// no colors.
-type Plain struct {
- // DisableTimestamp disables output of timestamp field.
- DisableTimestamp bool
- // DisableLevel disables output of level field.
- DisableLevel bool
- // DisableMsg disables output of msg field.
- DisableMsg bool
- // DisableContext disables output of all context fields.
- DisableContext bool
- // DisableStacktrace disables output of stack trace.
- DisableStacktrace bool
-
- // Delim is an optional delimiter output between each log field.
- // Defaults to a single space.
- Delim string
-
- // TimestampFormat is an optional format for timestamps. If empty
- // then DefTimestampFormat is used.
- TimestampFormat string
-}
-
-// Format converts a log record to bytes.
-func (p *Plain) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
- delim := p.Delim
- if delim == "" {
- delim = " "
- }
- if buf == nil {
- buf = &bytes.Buffer{}
- }
-
- timestampFmt := p.TimestampFormat
- if timestampFmt == "" {
- timestampFmt = logr.DefTimestampFormat
- }
-
- if !p.DisableTimestamp {
- var arr [128]byte
- tbuf := rec.Time().AppendFormat(arr[:0], timestampFmt)
- buf.Write(tbuf)
- buf.WriteString(delim)
- }
- if !p.DisableLevel {
- fmt.Fprintf(buf, "%v%s", rec.Level().Name, delim)
- }
- if !p.DisableMsg {
- fmt.Fprint(buf, rec.Msg(), delim)
- }
- if !p.DisableContext {
- ctx := rec.Fields()
- if len(ctx) > 0 {
- logr.WriteFields(buf, ctx, " ")
- }
- }
- if stacktrace && !p.DisableStacktrace {
- frames := rec.StackFrames()
- if len(frames) > 0 {
- buf.WriteString("\n")
- logr.WriteStacktrace(buf, rec.StackFrames())
- }
- }
- buf.WriteString("\n")
- return buf, nil
-}
diff --git a/vendor/github.com/mattermost/logr/formatter.go b/vendor/github.com/mattermost/logr/formatter.go
deleted file mode 100644
index bb8df2d414..0000000000
--- a/vendor/github.com/mattermost/logr/formatter.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package logr
-
-import (
- "bytes"
- "fmt"
- "io"
- "runtime"
- "sort"
-)
-
-// Formatter turns a LogRec into a formatted string.
-type Formatter interface {
- // Format converts a log record to bytes. If buf is not nil then it will be
- // be filled with the formatted results, otherwise a new buffer will be allocated.
- Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error)
-}
-
-const (
- // DefTimestampFormat is the default time stamp format used by
- // Plain formatter and others.
- DefTimestampFormat = "2006-01-02 15:04:05.000 Z07:00"
-)
-
-// DefaultFormatter is the default formatter, outputting only text with
-// no colors and a space delimiter. Use `format.Plain` instead.
-type DefaultFormatter struct {
-}
-
-// Format converts a log record to bytes.
-func (p *DefaultFormatter) Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
- if buf == nil {
- buf = &bytes.Buffer{}
- }
- delim := " "
- timestampFmt := DefTimestampFormat
-
- fmt.Fprintf(buf, "%s%s", rec.Time().Format(timestampFmt), delim)
- fmt.Fprintf(buf, "%v%s", rec.Level(), delim)
- fmt.Fprint(buf, rec.Msg(), delim)
-
- ctx := rec.Fields()
- if len(ctx) > 0 {
- WriteFields(buf, ctx, " ")
- }
-
- if stacktrace {
- frames := rec.StackFrames()
- if len(frames) > 0 {
- buf.WriteString("\n")
- WriteStacktrace(buf, rec.StackFrames())
- }
- }
- buf.WriteString("\n")
-
- return buf, nil
-}
-
-// WriteFields writes zero or more name value pairs to the io.Writer.
-// The pairs are sorted by key name and output in key=value format
-// with optional separator between fields.
-func WriteFields(w io.Writer, flds Fields, separator string) {
- keys := make([]string, 0, len(flds))
- for k := range flds {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- sep := ""
- for _, key := range keys {
- writeField(w, key, flds[key], sep)
- sep = separator
- }
-}
-
-func writeField(w io.Writer, key string, val interface{}, sep string) {
- var template string
- switch v := val.(type) {
- case error:
- val := v.Error()
- if shouldQuote(val) {
- template = "%s%s=%q"
- } else {
- template = "%s%s=%s"
- }
- case string:
- if shouldQuote(v) {
- template = "%s%s=%q"
- } else {
- template = "%s%s=%s"
- }
- default:
- template = "%s%s=%v"
- }
- fmt.Fprintf(w, template, sep, key, val)
-}
-
-// shouldQuote returns true if val contains any characters that might be unsafe
-// when injecting log output into an aggregator, viewer or report.
-func shouldQuote(val string) bool {
- for _, c := range val {
- if !((c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z')) {
- return true
- }
- }
- return false
-}
-
-// WriteStacktrace formats and outputs a stack trace to an io.Writer.
-func WriteStacktrace(w io.Writer, frames []runtime.Frame) {
- for _, frame := range frames {
- if frame.Function != "" {
- fmt.Fprintf(w, " %s\n", frame.Function)
- }
- if frame.File != "" {
- fmt.Fprintf(w, " %s:%d\n", frame.File, frame.Line)
- }
- }
-}
diff --git a/vendor/github.com/mattermost/logr/levelcustom.go b/vendor/github.com/mattermost/logr/levelcustom.go
deleted file mode 100644
index 384fe4e9ed..0000000000
--- a/vendor/github.com/mattermost/logr/levelcustom.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package logr
-
-import (
- "sync"
-)
-
-// CustomFilter allows targets to enable logging via a list of levels.
-type CustomFilter struct {
- mux sync.RWMutex
- levels map[LevelID]Level
-}
-
-// IsEnabled returns true if the specified Level exists in this list.
-func (st *CustomFilter) IsEnabled(level Level) bool {
- st.mux.RLock()
- defer st.mux.RUnlock()
- _, ok := st.levels[level.ID]
- return ok
-}
-
-// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
-func (st *CustomFilter) IsStacktraceEnabled(level Level) bool {
- st.mux.RLock()
- defer st.mux.RUnlock()
- lvl, ok := st.levels[level.ID]
- if ok {
- return lvl.Stacktrace
- }
- return false
-}
-
-// Add adds one or more levels to the list. Adding a level enables logging for
-// that level on any targets using this CustomFilter.
-func (st *CustomFilter) Add(levels ...Level) {
- st.mux.Lock()
- defer st.mux.Unlock()
-
- if st.levels == nil {
- st.levels = make(map[LevelID]Level)
- }
-
- for _, s := range levels {
- st.levels[s.ID] = s
- }
-}
diff --git a/vendor/github.com/mattermost/logr/levelstd.go b/vendor/github.com/mattermost/logr/levelstd.go
deleted file mode 100644
index f5e0fa4664..0000000000
--- a/vendor/github.com/mattermost/logr/levelstd.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package logr
-
-// StdFilter allows targets to filter via classic log levels where any level
-// beyond a certain verbosity/severity is enabled.
-type StdFilter struct {
- Lvl Level
- Stacktrace Level
-}
-
-// IsEnabled returns true if the specified Level is at or above this verbosity. Also
-// determines if a stack trace is required.
-func (lt StdFilter) IsEnabled(level Level) bool {
- return level.ID <= lt.Lvl.ID
-}
-
-// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
-func (lt StdFilter) IsStacktraceEnabled(level Level) bool {
- return level.ID <= lt.Stacktrace.ID
-}
-
-var (
- // Panic is the highest level of severity. Logs the message and then panics.
- Panic = Level{ID: 0, Name: "panic"}
- // Fatal designates a catastrophic error. Logs the message and then calls
- // `logr.Exit(1)`.
- Fatal = Level{ID: 1, Name: "fatal"}
- // Error designates a serious but possibly recoverable error.
- Error = Level{ID: 2, Name: "error"}
- // Warn designates non-critical error.
- Warn = Level{ID: 3, Name: "warn"}
- // Info designates information regarding application events.
- Info = Level{ID: 4, Name: "info"}
- // Debug designates verbose information typically used for debugging.
- Debug = Level{ID: 5, Name: "debug"}
- // Trace designates the highest verbosity of log output.
- Trace = Level{ID: 6, Name: "trace"}
-)
diff --git a/vendor/github.com/mattermost/logr/logger.go b/vendor/github.com/mattermost/logr/logger.go
deleted file mode 100644
index c2386312f0..0000000000
--- a/vendor/github.com/mattermost/logr/logger.go
+++ /dev/null
@@ -1,218 +0,0 @@
-package logr
-
-import (
- "fmt"
-)
-
-// Fields type, used to pass to `WithFields`.
-type Fields map[string]interface{}
-
-// Logger provides context for logging via fields.
-type Logger struct {
- logr *Logr
- fields Fields
-}
-
-// Logr returns the `Logr` instance that created this `Logger`.
-func (logger Logger) Logr() *Logr {
- return logger.logr
-}
-
-// WithField creates a new `Logger` with any existing fields
-// plus the new one.
-func (logger Logger) WithField(key string, value interface{}) Logger {
- return logger.WithFields(Fields{key: value})
-}
-
-// WithFields creates a new `Logger` with any existing fields
-// plus the new ones.
-func (logger Logger) WithFields(fields Fields) Logger {
- l := Logger{logr: logger.logr}
- // if parent has no fields then avoid creating a new map.
- oldLen := len(logger.fields)
- if oldLen == 0 {
- l.fields = fields
- return l
- }
-
- l.fields = make(Fields, len(fields)+oldLen)
- for k, v := range logger.fields {
- l.fields[k] = v
- }
- for k, v := range fields {
- l.fields[k] = v
- }
- return l
-}
-
-// Log checks that the level matches one or more targets, and
-// if so, generates a log record that is added to the Logr queue.
-// Arguments are handled in the manner of fmt.Print.
-func (logger Logger) Log(lvl Level, args ...interface{}) {
- status := logger.logr.IsLevelEnabled(lvl)
- if status.Enabled {
- rec := NewLogRec(lvl, logger, "", args, status.Stacktrace)
- logger.logr.enqueue(rec)
- }
-}
-
-// Trace is a convenience method equivalent to `Log(TraceLevel, args...)`.
-func (logger Logger) Trace(args ...interface{}) {
- logger.Log(Trace, args...)
-}
-
-// Debug is a convenience method equivalent to `Log(DebugLevel, args...)`.
-func (logger Logger) Debug(args ...interface{}) {
- logger.Log(Debug, args...)
-}
-
-// Print ensures compatibility with std lib logger.
-func (logger Logger) Print(args ...interface{}) {
- logger.Info(args...)
-}
-
-// Info is a convenience method equivalent to `Log(InfoLevel, args...)`.
-func (logger Logger) Info(args ...interface{}) {
- logger.Log(Info, args...)
-}
-
-// Warn is a convenience method equivalent to `Log(WarnLevel, args...)`.
-func (logger Logger) Warn(args ...interface{}) {
- logger.Log(Warn, args...)
-}
-
-// Error is a convenience method equivalent to `Log(ErrorLevel, args...)`.
-func (logger Logger) Error(args ...interface{}) {
- logger.Log(Error, args...)
-}
-
-// Fatal is a convenience method equivalent to `Log(FatalLevel, args...)`
-// followed by a call to os.Exit(1).
-func (logger Logger) Fatal(args ...interface{}) {
- logger.Log(Fatal, args...)
- logger.logr.exit(1)
-}
-
-// Panic is a convenience method equivalent to `Log(PanicLevel, args...)`
-// followed by a call to panic().
-func (logger Logger) Panic(args ...interface{}) {
- logger.Log(Panic, args...)
- panic(fmt.Sprint(args...))
-}
-
-//
-// Printf style
-//
-
-// Logf checks that the level matches one or more targets, and
-// if so, generates a log record that is added to the main
-// queue (channel). Arguments are handled in the manner of fmt.Printf.
-func (logger Logger) Logf(lvl Level, format string, args ...interface{}) {
- status := logger.logr.IsLevelEnabled(lvl)
- if status.Enabled {
- rec := NewLogRec(lvl, logger, format, args, status.Stacktrace)
- logger.logr.enqueue(rec)
- }
-}
-
-// Tracef is a convenience method equivalent to `Logf(TraceLevel, args...)`.
-func (logger Logger) Tracef(format string, args ...interface{}) {
- logger.Logf(Trace, format, args...)
-}
-
-// Debugf is a convenience method equivalent to `Logf(DebugLevel, args...)`.
-func (logger Logger) Debugf(format string, args ...interface{}) {
- logger.Logf(Debug, format, args...)
-}
-
-// Infof is a convenience method equivalent to `Logf(InfoLevel, args...)`.
-func (logger Logger) Infof(format string, args ...interface{}) {
- logger.Logf(Info, format, args...)
-}
-
-// Printf ensures compatibility with std lib logger.
-func (logger Logger) Printf(format string, args ...interface{}) {
- logger.Infof(format, args...)
-}
-
-// Warnf is a convenience method equivalent to `Logf(WarnLevel, args...)`.
-func (logger Logger) Warnf(format string, args ...interface{}) {
- logger.Logf(Warn, format, args...)
-}
-
-// Errorf is a convenience method equivalent to `Logf(ErrorLevel, args...)`.
-func (logger Logger) Errorf(format string, args ...interface{}) {
- logger.Logf(Error, format, args...)
-}
-
-// Fatalf is a convenience method equivalent to `Logf(FatalLevel, args...)`
-// followed by a call to os.Exit(1).
-func (logger Logger) Fatalf(format string, args ...interface{}) {
- logger.Logf(Fatal, format, args...)
- logger.logr.exit(1)
-}
-
-// Panicf is a convenience method equivalent to `Logf(PanicLevel, args...)`
-// followed by a call to panic().
-func (logger Logger) Panicf(format string, args ...interface{}) {
- logger.Logf(Panic, format, args...)
-}
-
-//
-// Println style
-//
-
-// Logln checks that the level matches one or more targets, and
-// if so, generates a log record that is added to the main
-// queue (channel). Arguments are handled in the manner of fmt.Println.
-func (logger Logger) Logln(lvl Level, args ...interface{}) {
- status := logger.logr.IsLevelEnabled(lvl)
- if status.Enabled {
- rec := NewLogRec(lvl, logger, "", args, status.Stacktrace)
- rec.newline = true
- logger.logr.enqueue(rec)
- }
-}
-
-// Traceln is a convenience method equivalent to `Logln(TraceLevel, args...)`.
-func (logger Logger) Traceln(args ...interface{}) {
- logger.Logln(Trace, args...)
-}
-
-// Debugln is a convenience method equivalent to `Logln(DebugLevel, args...)`.
-func (logger Logger) Debugln(args ...interface{}) {
- logger.Logln(Debug, args...)
-}
-
-// Infoln is a convenience method equivalent to `Logln(InfoLevel, args...)`.
-func (logger Logger) Infoln(args ...interface{}) {
- logger.Logln(Info, args...)
-}
-
-// Println ensures compatibility with std lib logger.
-func (logger Logger) Println(args ...interface{}) {
- logger.Infoln(args...)
-}
-
-// Warnln is a convenience method equivalent to `Logln(WarnLevel, args...)`.
-func (logger Logger) Warnln(args ...interface{}) {
- logger.Logln(Warn, args...)
-}
-
-// Errorln is a convenience method equivalent to `Logln(ErrorLevel, args...)`.
-func (logger Logger) Errorln(args ...interface{}) {
- logger.Logln(Error, args...)
-}
-
-// Fatalln is a convenience method equivalent to `Logln(FatalLevel, args...)`
-// followed by a call to os.Exit(1).
-func (logger Logger) Fatalln(args ...interface{}) {
- logger.Logln(Fatal, args...)
- logger.logr.exit(1)
-}
-
-// Panicln is a convenience method equivalent to `Logln(PanicLevel, args...)`
-// followed by a call to panic().
-func (logger Logger) Panicln(args ...interface{}) {
- logger.Logln(Panic, args...)
-}
diff --git a/vendor/github.com/mattermost/logr/logr.go b/vendor/github.com/mattermost/logr/logr.go
deleted file mode 100644
index 631366a570..0000000000
--- a/vendor/github.com/mattermost/logr/logr.go
+++ /dev/null
@@ -1,664 +0,0 @@
-package logr
-
-import (
- "bytes"
- "context"
- "errors"
- "fmt"
- "os"
- "sync"
- "time"
-
- "github.com/wiggin77/cfg"
- "github.com/wiggin77/merror"
-)
-
-// Logr maintains a list of log targets and accepts incoming
-// log records.
-type Logr struct {
- tmux sync.RWMutex // target mutex
- targets []Target
-
- mux sync.RWMutex
- maxQueueSizeActual int
- in chan *LogRec
- done chan struct{}
- once sync.Once
- shutdown bool
- lvlCache levelCache
-
- metricsInitOnce sync.Once
- metricsCloseOnce sync.Once
- metricsDone chan struct{}
- metrics MetricsCollector
- queueSizeGauge Gauge
- loggedCounter Counter
- errorCounter Counter
-
- bufferPool sync.Pool
-
- // 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.
- // If this is modified, it must be done before `Configure` or
- // `AddTarget`. Defaults to DefaultMaxQueueSize.
- MaxQueueSize int
-
- // 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.
- OnLoggerError func(error)
-
- // 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.
- OnQueueFull func(rec *LogRec, maxQueueSize int) bool
-
- // 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.
- OnTargetQueueFull func(target Target, rec *LogRec, maxQueueSize int) bool
-
- // OnExit, when not nil, is called when a FatalXXX style log API is called.
- // When nil, then the default behavior is to cleanly shut down this Logr and
- // call `os.Exit(code)`.
- OnExit func(code int)
-
- // OnPanic, when not nil, is called when a PanicXXX style log API is called.
- // When nil, then the default behavior is to cleanly shut down this Logr and
- // call `panic(err)`.
- OnPanic func(err interface{})
-
- // EnqueueTimeout is the amount of time a log record can take to be queued.
- // This only applies to blocking enqueue which happen after `logr.OnQueueFull`
- // is called and returns false.
- EnqueueTimeout time.Duration
-
- // ShutdownTimeout is the amount of time `logr.Shutdown` can execute before
- // timing out.
- ShutdownTimeout time.Duration
-
- // FlushTimeout is the amount of time `logr.Flush` can execute before
- // timing out.
- FlushTimeout time.Duration
-
- // UseSyncMapLevelCache can be set to true before the first target is added
- // when high concurrency (e.g. >32 cores) is expected. This may improve
- // performance with large numbers of cores - benchmark for your use case.
- UseSyncMapLevelCache bool
-
- // MaxPooledFormatBuffer determines the maximum size of a buffer that can be
- // pooled. To reduce allocations, the buffers needed during formatting (etc)
- // are pooled. A very large log item will grow a buffer that could stay in
- // memory indefinitely. This settings lets you control how big a pooled buffer
- // can be - anything larger will be garbage collected after use.
- // Defaults to 1MB.
- MaxPooledBuffer int
-
- // DisableBufferPool when true disables the buffer pool. See MaxPooledBuffer.
- DisableBufferPool bool
-
- // MetricsUpdateFreqMillis determines how often polled metrics are updated
- // when metrics are enabled.
- MetricsUpdateFreqMillis int64
-}
-
-// Configure adds/removes targets via the supplied `Config`.
-func (logr *Logr) Configure(config *cfg.Config) error {
- // TODO
- return fmt.Errorf("not implemented yet")
-}
-
-func (logr *Logr) ensureInit() {
- logr.once.Do(func() {
- defer func() {
- go logr.start()
- }()
-
- logr.mux.Lock()
- defer logr.mux.Unlock()
-
- logr.maxQueueSizeActual = logr.MaxQueueSize
- if logr.maxQueueSizeActual == 0 {
- logr.maxQueueSizeActual = DefaultMaxQueueSize
- }
-
- if logr.maxQueueSizeActual < 0 {
- logr.maxQueueSizeActual = 0
- }
-
- logr.in = make(chan *LogRec, logr.maxQueueSizeActual)
- logr.done = make(chan struct{})
-
- if logr.UseSyncMapLevelCache {
- logr.lvlCache = &syncMapLevelCache{}
- } else {
- logr.lvlCache = &arrayLevelCache{}
- }
-
- if logr.MaxPooledBuffer == 0 {
- logr.MaxPooledBuffer = DefaultMaxPooledBuffer
- }
- logr.bufferPool = sync.Pool{
- New: func() interface{} {
- return new(bytes.Buffer)
- },
- }
-
- logr.lvlCache.setup()
- })
-}
-
-// AddTarget adds one or more targets to the logger which will receive
-// log records for outputting.
-func (logr *Logr) AddTarget(targets ...Target) error {
- if logr.IsShutdown() {
- return fmt.Errorf("AddTarget called after Logr shut down")
- }
-
- logr.ensureInit()
- metrics := logr.getMetricsCollector()
- defer logr.ResetLevelCache() // call this after tmux is released
-
- logr.tmux.Lock()
- defer logr.tmux.Unlock()
-
- errs := merror.New()
- for _, t := range targets {
- if t == nil {
- continue
- }
-
- logr.targets = append(logr.targets, t)
- if metrics != nil {
- if tm, ok := t.(TargetWithMetrics); ok {
- if err := tm.EnableMetrics(metrics, logr.MetricsUpdateFreqMillis); err != nil {
- errs.Append(err)
- }
- }
- }
- }
- return errs.ErrorOrNil()
-}
-
-// NewLogger creates a Logger using defaults. A `Logger` is light-weight
-// enough to create on-demand, but typically one or more Loggers are
-// created and re-used.
-func (logr *Logr) NewLogger() Logger {
- logger := Logger{logr: logr}
- return logger
-}
-
-var levelStatusDisabled = LevelStatus{}
-
-// IsLevelEnabled returns true if at least one target has the specified
-// level enabled. The result is cached so that subsequent checks are fast.
-func (logr *Logr) IsLevelEnabled(lvl Level) LevelStatus {
- status, ok := logr.isLevelEnabledFromCache(lvl)
- if ok {
- return status
- }
-
- // Check each target.
- logr.tmux.RLock()
- for _, t := range logr.targets {
- e, s := t.IsLevelEnabled(lvl)
- if e {
- status.Enabled = true
- if s {
- status.Stacktrace = true
- break // if both enabled then no sense checking more targets
- }
- }
- }
- logr.tmux.RUnlock()
-
- // Cache and return the result.
- if err := logr.updateLevelCache(lvl.ID, status); err != nil {
- logr.ReportError(err)
- return LevelStatus{}
- }
- return status
-}
-
-func (logr *Logr) isLevelEnabledFromCache(lvl Level) (LevelStatus, bool) {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
-
- // Don't accept new log records after shutdown.
- if logr.shutdown {
- return levelStatusDisabled, true
- }
-
- // Check cache. lvlCache may still be nil if no targets added.
- if logr.lvlCache == nil {
- return levelStatusDisabled, true
- }
- status, ok := logr.lvlCache.get(lvl.ID)
- if ok {
- return status, true
- }
- return LevelStatus{}, false
-}
-
-func (logr *Logr) updateLevelCache(id LevelID, status LevelStatus) error {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
- if logr.lvlCache != nil {
- return logr.lvlCache.put(id, status)
- }
- return nil
-}
-
-// HasTargets returns true only if at least one target exists within the Logr.
-func (logr *Logr) HasTargets() bool {
- logr.tmux.RLock()
- defer logr.tmux.RUnlock()
- return len(logr.targets) > 0
-}
-
-// TargetInfo provides name and type for a Target.
-type TargetInfo struct {
- Name string
- Type string
-}
-
-// TargetInfos enumerates all the targets added to this Logr.
-// The resulting slice represents a snapshot at time of calling.
-func (logr *Logr) TargetInfos() []TargetInfo {
- logr.tmux.RLock()
- defer logr.tmux.RUnlock()
-
- infos := make([]TargetInfo, 0)
-
- for _, t := range logr.targets {
- inf := TargetInfo{
- Name: fmt.Sprintf("%v", t),
- Type: fmt.Sprintf("%T", t),
- }
- infos = append(infos, inf)
- }
- return infos
-}
-
-// 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 (logr *Logr) RemoveTargets(cxt context.Context, f func(ti TargetInfo) bool) error {
- var removed bool
- defer func() {
- if removed {
- // call this after tmux is released since
- // it will lock mux and we don't want to
- // introduce possible deadlock.
- logr.ResetLevelCache()
- }
- }()
-
- errs := merror.New()
-
- logr.tmux.Lock()
- defer logr.tmux.Unlock()
-
- cp := make([]Target, 0)
-
- for _, t := range logr.targets {
- inf := TargetInfo{
- Name: fmt.Sprintf("%v", t),
- Type: fmt.Sprintf("%T", t),
- }
- if f(inf) {
- if err := t.Shutdown(cxt); err != nil {
- errs.Append(err)
- }
- removed = true
- } else {
- cp = append(cp, t)
- }
- }
- logr.targets = cp
- return errs.ErrorOrNil()
-}
-
-// ResetLevelCache resets the cached results of `IsLevelEnabled`. This is
-// called any time a Target is added or a target's level is changed.
-func (logr *Logr) ResetLevelCache() {
- // Write lock so that new cache entries cannot be stored while we
- // clear the cache.
- logr.mux.Lock()
- defer logr.mux.Unlock()
- logr.resetLevelCache()
-}
-
-// resetLevelCache empties the level cache without locking.
-// mux.Lock must be held before calling this function.
-func (logr *Logr) resetLevelCache() {
- // lvlCache may still be nil if no targets added.
- if logr.lvlCache != nil {
- logr.lvlCache.clear()
- }
-}
-
-// enqueue adds a log record to the logr queue. If the queue is full then
-// this function either blocks or the log record is dropped, depending on
-// the result of calling `OnQueueFull`.
-func (logr *Logr) enqueue(rec *LogRec) {
- if logr.in == nil {
- logr.ReportError(fmt.Errorf("AddTarget or Configure must be called before enqueue"))
- }
-
- select {
- case logr.in <- rec:
- default:
- if logr.OnQueueFull != nil && logr.OnQueueFull(rec, logr.maxQueueSizeActual) {
- return // drop the record
- }
- select {
- case <-time.After(logr.enqueueTimeout()):
- logr.ReportError(fmt.Errorf("enqueue timed out for log rec [%v]", rec))
- case logr.in <- rec: // block until success or timeout
- }
- }
-}
-
-// exit is called by one of the FatalXXX style APIS. If `logr.OnExit` is not nil
-// then that method is called, otherwise the default behavior is to shut down this
-// Logr cleanly then call `os.Exit(code)`.
-func (logr *Logr) exit(code int) {
- if logr.OnExit != nil {
- logr.OnExit(code)
- return
- }
-
- if err := logr.Shutdown(); err != nil {
- logr.ReportError(err)
- }
- os.Exit(code)
-}
-
-// panic is called by one of the PanicXXX style APIS. If `logr.OnPanic` is not nil
-// then that method is called, otherwise the default behavior is to shut down this
-// Logr cleanly then call `panic(err)`.
-func (logr *Logr) panic(err interface{}) {
- if logr.OnPanic != nil {
- logr.OnPanic(err)
- return
- }
-
- if err := logr.Shutdown(); err != nil {
- logr.ReportError(err)
- }
- panic(err)
-}
-
-// Flush blocks while flushing the logr queue and all target queues, by
-// writing existing log records to valid targets.
-// Any attempts to add new log records will block until flush is complete.
-// `logr.FlushTimeout` determines how long flush can execute before
-// timing out. Use `IsTimeoutError` to determine if the returned error is
-// due to a timeout.
-func (logr *Logr) Flush() error {
- ctx, cancel := context.WithTimeout(context.Background(), logr.flushTimeout())
- defer cancel()
- return logr.FlushWithTimeout(ctx)
-}
-
-// Flush blocks while flushing the logr queue and all target queues, by
-// writing existing log records to valid targets.
-// Any attempts to add new log records will block until flush is complete.
-// Use `IsTimeoutError` to determine if the returned error is
-// due to a timeout.
-func (logr *Logr) FlushWithTimeout(ctx context.Context) error {
- if !logr.HasTargets() {
- return nil
- }
-
- if logr.IsShutdown() {
- return errors.New("Flush called on shut down Logr")
- }
-
- rec := newFlushLogRec(logr.NewLogger())
- logr.enqueue(rec)
-
- select {
- case <-ctx.Done():
- return newTimeoutError("logr queue shutdown timeout")
- case <-rec.flush:
- }
- return nil
-}
-
-// IsShutdown returns true if this Logr instance has been shut down.
-// No further log records can be enqueued and no targets added after
-// shutdown.
-func (logr *Logr) IsShutdown() bool {
- logr.mux.Lock()
- defer logr.mux.Unlock()
- return logr.shutdown
-}
-
-// Shutdown cleanly stops the logging engine after making best efforts
-// to flush all targets. Call this function right before application
-// exit - logr cannot be restarted once shut down.
-// `logr.ShutdownTimeout` determines how long shutdown can execute before
-// timing out. Use `IsTimeoutError` to determine if the returned error is
-// due to a timeout.
-func (logr *Logr) Shutdown() error {
- ctx, cancel := context.WithTimeout(context.Background(), logr.shutdownTimeout())
- defer cancel()
- return logr.ShutdownWithTimeout(ctx)
-}
-
-// Shutdown cleanly stops the logging engine after making best efforts
-// to flush all targets. Call this function right before application
-// exit - logr cannot be restarted once shut down.
-// Use `IsTimeoutError` to determine if the returned error is due to a
-// timeout.
-func (logr *Logr) ShutdownWithTimeout(ctx context.Context) error {
- logr.mux.Lock()
- if logr.shutdown {
- logr.mux.Unlock()
- return errors.New("Shutdown called again after shut down")
- }
- logr.shutdown = true
- logr.resetLevelCache()
- logr.mux.Unlock()
-
- logr.metricsCloseOnce.Do(func() {
- if logr.metricsDone != nil {
- close(logr.metricsDone)
- }
- })
-
- errs := merror.New()
-
- // close the incoming channel and wait for read loop to exit.
- if logr.in != nil {
- close(logr.in)
- select {
- case <-ctx.Done():
- errs.Append(newTimeoutError("logr queue shutdown timeout"))
- case <-logr.done:
- }
- }
-
- // logr.in channel should now be drained to targets and no more log records
- // can be added.
- logr.tmux.RLock()
- defer logr.tmux.RUnlock()
- for _, t := range logr.targets {
- err := t.Shutdown(ctx)
- if err != nil {
- errs.Append(err)
- }
- }
- return errs.ErrorOrNil()
-}
-
-// ReportError is used to notify the host application of any internal logging errors.
-// If `OnLoggerError` is not nil, it is called with the error, otherwise the error is
-// output to `os.Stderr`.
-func (logr *Logr) ReportError(err interface{}) {
- logr.incErrorCounter()
-
- if logr.OnLoggerError == nil {
- fmt.Fprintln(os.Stderr, err)
- return
- }
- logr.OnLoggerError(fmt.Errorf("%v", err))
-}
-
-// BorrowBuffer borrows a buffer from the pool. Release the buffer to reduce garbage collection.
-func (logr *Logr) BorrowBuffer() *bytes.Buffer {
- if logr.DisableBufferPool {
- return &bytes.Buffer{}
- }
- return logr.bufferPool.Get().(*bytes.Buffer)
-}
-
-// ReleaseBuffer returns a buffer to the pool to reduce garbage collection. The buffer is only
-// retained if less than MaxPooledBuffer.
-func (logr *Logr) ReleaseBuffer(buf *bytes.Buffer) {
- if !logr.DisableBufferPool && buf.Cap() < logr.MaxPooledBuffer {
- buf.Reset()
- logr.bufferPool.Put(buf)
- }
-}
-
-// enqueueTimeout returns amount of time a log record can take to be queued.
-// This only applies to blocking enqueue which happen after `logr.OnQueueFull` is called
-// and returns false.
-func (logr *Logr) enqueueTimeout() time.Duration {
- if logr.EnqueueTimeout == 0 {
- return DefaultEnqueueTimeout
- }
- return logr.EnqueueTimeout
-}
-
-// shutdownTimeout returns the timeout duration for `logr.Shutdown`.
-func (logr *Logr) shutdownTimeout() time.Duration {
- if logr.ShutdownTimeout == 0 {
- return DefaultShutdownTimeout
- }
- return logr.ShutdownTimeout
-}
-
-// flushTimeout returns the timeout duration for `logr.Flush`.
-func (logr *Logr) flushTimeout() time.Duration {
- if logr.FlushTimeout == 0 {
- return DefaultFlushTimeout
- }
- return logr.FlushTimeout
-}
-
-// start selects on incoming log records until done channel signals.
-// Incoming log records are fanned out to all log targets.
-func (logr *Logr) start() {
- defer func() {
- if r := recover(); r != nil {
- logr.ReportError(r)
- go logr.start()
- }
- }()
-
- for rec := range logr.in {
- if rec.flush != nil {
- logr.flush(rec.flush)
- } else {
- rec.prep()
- logr.fanout(rec)
- }
- }
- close(logr.done)
-}
-
-// startMetricsUpdater updates the metrics for any polled values every `MetricsUpdateFreqSecs` seconds until
-// logr is closed.
-func (logr *Logr) startMetricsUpdater() {
- for {
- updateFreq := logr.getMetricsUpdateFreqMillis()
- if updateFreq == 0 {
- updateFreq = DefMetricsUpdateFreqMillis
- }
- if updateFreq < 250 {
- updateFreq = 250 // don't peg the CPU
- }
-
- select {
- case <-logr.metricsDone:
- return
- case <-time.After(time.Duration(updateFreq) * time.Millisecond):
- logr.setQueueSizeGauge(float64(len(logr.in)))
- }
- }
-}
-
-func (logr *Logr) getMetricsUpdateFreqMillis() int64 {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
- return logr.MetricsUpdateFreqMillis
-}
-
-// fanout pushes a LogRec to all targets.
-func (logr *Logr) fanout(rec *LogRec) {
- var target Target
- defer func() {
- if r := recover(); r != nil {
- logr.ReportError(fmt.Errorf("fanout failed for target %s, %v", target, r))
- }
- }()
-
- var logged bool
- defer func() {
- if logged {
- logr.incLoggedCounter() // call this after tmux is released
- }
- }()
-
- logr.tmux.RLock()
- defer logr.tmux.RUnlock()
- for _, target = range logr.targets {
- if enabled, _ := target.IsLevelEnabled(rec.Level()); enabled {
- target.Log(rec)
- logged = true
- }
- }
-}
-
-// flush drains the queue and notifies when done.
-func (logr *Logr) flush(done chan<- struct{}) {
- // first drain the logr queue.
-loop:
- for {
- var rec *LogRec
- select {
- case rec = <-logr.in:
- if rec.flush == nil {
- rec.prep()
- logr.fanout(rec)
- }
- default:
- break loop
- }
- }
-
- logger := logr.NewLogger()
-
- // drain all the targets; block until finished.
- logr.tmux.RLock()
- defer logr.tmux.RUnlock()
- for _, target := range logr.targets {
- rec := newFlushLogRec(logger)
- target.Log(rec)
- <-rec.flush
- }
- done <- struct{}{}
-}
diff --git a/vendor/github.com/mattermost/logr/target.go b/vendor/github.com/mattermost/logr/target.go
deleted file mode 100644
index f8e7bf752c..0000000000
--- a/vendor/github.com/mattermost/logr/target.go
+++ /dev/null
@@ -1,299 +0,0 @@
-package logr
-
-import (
- "context"
- "fmt"
- "os"
- "sync"
- "time"
-)
-
-// Target represents a destination for log records such as file,
-// database, TCP socket, etc.
-type Target interface {
- // SetName provides an optional name for the target.
- SetName(name string)
-
- // IsLevelEnabled returns true if this target should emit
- // logs for the specified level. Also determines if
- // a stack trace is required.
- IsLevelEnabled(Level) (enabled bool, stacktrace bool)
-
- // Formatter returns the Formatter associated with this Target.
- Formatter() Formatter
-
- // Log outputs the log record to this target's destination.
- Log(rec *LogRec)
-
- // Shutdown makes best effort to flush target queue and
- // frees/closes all resources.
- Shutdown(ctx context.Context) error
-}
-
-// RecordWriter can convert a LogRecord to bytes and output to some data sink.
-type RecordWriter interface {
- Write(rec *LogRec) error
-}
-
-// Basic provides the basic functionality of a Target that can be used
-// to more easily compose your own Targets. To use, just embed Basic
-// in your target type, implement `RecordWriter`, and call `(*Basic).Start`.
-type Basic struct {
- target Target
-
- filter Filter
- formatter Formatter
-
- in chan *LogRec
- done chan struct{}
- w RecordWriter
-
- mux sync.RWMutex
- name string
-
- metrics bool
- queueSizeGauge Gauge
- loggedCounter Counter
- errorCounter Counter
- droppedCounter Counter
- blockedCounter Counter
-
- metricsUpdateFreqMillis int64
-}
-
-// Start initializes this target helper and starts accepting log records for processing.
-func (b *Basic) Start(target Target, rw RecordWriter, filter Filter, formatter Formatter, maxQueued int) {
- if filter == nil {
- filter = &StdFilter{Lvl: Fatal}
- }
- if formatter == nil {
- formatter = &DefaultFormatter{}
- }
-
- b.target = target
- b.filter = filter
- b.formatter = formatter
- b.in = make(chan *LogRec, maxQueued)
- b.done = make(chan struct{}, 1)
- b.w = rw
- go b.start()
-
- if b.hasMetrics() {
- go b.startMetricsUpdater()
- }
-}
-
-func (b *Basic) SetName(name string) {
- b.mux.Lock()
- defer b.mux.Unlock()
- b.name = name
-}
-
-// IsLevelEnabled returns true if this target should emit
-// logs for the specified level. Also determines if
-// a stack trace is required.
-func (b *Basic) IsLevelEnabled(lvl Level) (enabled bool, stacktrace bool) {
- return b.filter.IsEnabled(lvl), b.filter.IsStacktraceEnabled(lvl)
-}
-
-// Formatter returns the Formatter associated with this Target.
-func (b *Basic) Formatter() Formatter {
- return b.formatter
-}
-
-// Shutdown stops processing log records after making best
-// effort to flush queue.
-func (b *Basic) Shutdown(ctx context.Context) error {
- // close the incoming channel and wait for read loop to exit.
- close(b.in)
- select {
- case <-ctx.Done():
- case <-b.done:
- }
-
- // b.in channel should now be drained.
- return nil
-}
-
-// Log outputs the log record to this targets destination.
-func (b *Basic) Log(rec *LogRec) {
- lgr := rec.Logger().Logr()
- select {
- case b.in <- rec:
- default:
- handler := lgr.OnTargetQueueFull
- if handler != nil && handler(b.target, rec, cap(b.in)) {
- b.incDroppedCounter()
- return // drop the record
- }
- b.incBlockedCounter()
-
- select {
- case <-time.After(lgr.enqueueTimeout()):
- lgr.ReportError(fmt.Errorf("target enqueue timeout for log rec [%v]", rec))
- case b.in <- rec: // block until success or timeout
- }
- }
-}
-
-// Metrics enables metrics collection using the provided MetricsCollector.
-func (b *Basic) EnableMetrics(collector MetricsCollector, updateFreqMillis int64) error {
- name := fmt.Sprintf("%v", b)
-
- b.mux.Lock()
- defer b.mux.Unlock()
-
- b.metrics = true
- b.metricsUpdateFreqMillis = updateFreqMillis
-
- var err error
-
- if b.queueSizeGauge, err = collector.QueueSizeGauge(name); err != nil {
- return err
- }
- if b.loggedCounter, err = collector.LoggedCounter(name); err != nil {
- return err
- }
- if b.errorCounter, err = collector.ErrorCounter(name); err != nil {
- return err
- }
- if b.droppedCounter, err = collector.DroppedCounter(name); err != nil {
- return err
- }
- if b.blockedCounter, err = collector.BlockedCounter(name); err != nil {
- return err
- }
- return nil
-}
-
-func (b *Basic) hasMetrics() bool {
- b.mux.RLock()
- defer b.mux.RUnlock()
- return b.metrics
-}
-
-func (b *Basic) setQueueSizeGauge(val float64) {
- b.mux.RLock()
- defer b.mux.RUnlock()
- if b.queueSizeGauge != nil {
- b.queueSizeGauge.Set(val)
- }
-}
-
-func (b *Basic) incLoggedCounter() {
- b.mux.RLock()
- defer b.mux.RUnlock()
- if b.loggedCounter != nil {
- b.loggedCounter.Inc()
- }
-}
-
-func (b *Basic) incErrorCounter() {
- b.mux.RLock()
- defer b.mux.RUnlock()
- if b.errorCounter != nil {
- b.errorCounter.Inc()
- }
-}
-
-func (b *Basic) incDroppedCounter() {
- b.mux.RLock()
- defer b.mux.RUnlock()
- if b.droppedCounter != nil {
- b.droppedCounter.Inc()
- }
-}
-
-func (b *Basic) incBlockedCounter() {
- b.mux.RLock()
- defer b.mux.RUnlock()
- if b.blockedCounter != nil {
- b.blockedCounter.Inc()
- }
-}
-
-// String returns a name for this target. Use `SetName` to specify a name.
-func (b *Basic) String() string {
- b.mux.RLock()
- defer b.mux.RUnlock()
-
- if b.name != "" {
- return b.name
- }
- return fmt.Sprintf("%T", b.target)
-}
-
-// Start accepts log records via In channel and writes to the
-// supplied writer, until Done channel signaled.
-func (b *Basic) start() {
- defer func() {
- if r := recover(); r != nil {
- fmt.Fprintln(os.Stderr, "Basic.start -- ", r)
- go b.start()
- }
- }()
-
- for rec := range b.in {
- if rec.flush != nil {
- b.flush(rec.flush)
- } else {
- err := b.w.Write(rec)
- if err != nil {
- b.incErrorCounter()
- rec.Logger().Logr().ReportError(err)
- } else {
- b.incLoggedCounter()
- }
- }
- }
- close(b.done)
-}
-
-// startMetricsUpdater updates the metrics for any polled values every `MetricsUpdateFreqSecs` seconds until
-// target is closed.
-func (b *Basic) startMetricsUpdater() {
- for {
- updateFreq := b.getMetricsUpdateFreqMillis()
- if updateFreq == 0 {
- updateFreq = DefMetricsUpdateFreqMillis
- }
- if updateFreq < 250 {
- updateFreq = 250 // don't peg the CPU
- }
-
- select {
- case <-b.done:
- return
- case <-time.After(time.Duration(updateFreq) * time.Millisecond):
- b.setQueueSizeGauge(float64(len(b.in)))
- }
- }
-}
-
-func (b *Basic) getMetricsUpdateFreqMillis() int64 {
- b.mux.RLock()
- defer b.mux.RUnlock()
- return b.metricsUpdateFreqMillis
-}
-
-// flush drains the queue and notifies when done.
-func (b *Basic) flush(done chan<- struct{}) {
- for {
- var rec *LogRec
- var err error
- select {
- case rec = <-b.in:
- // ignore any redundant flush records.
- if rec.flush == nil {
- err = b.w.Write(rec)
- if err != nil {
- b.incErrorCounter()
- rec.Logger().Logr().ReportError(err)
- }
- }
- default:
- done <- struct{}{}
- return
- }
- }
-}
diff --git a/vendor/github.com/mattermost/logr/target/syslog.go b/vendor/github.com/mattermost/logr/target/syslog.go
deleted file mode 100644
index 1d2013b681..0000000000
--- a/vendor/github.com/mattermost/logr/target/syslog.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// +build !windows,!nacl,!plan9
-
-package target
-
-import (
- "context"
- "fmt"
- "log/syslog"
-
- "github.com/mattermost/logr"
- "github.com/wiggin77/merror"
-)
-
-// Syslog outputs log records to local or remote syslog.
-type Syslog struct {
- logr.Basic
- w *syslog.Writer
-}
-
-// SyslogParams provides parameters for dialing a syslog daemon.
-type SyslogParams struct {
- Network string
- Raddr string
- Priority syslog.Priority
- Tag string
-}
-
-// NewSyslogTarget creates a target capable of outputting log records to remote or local syslog.
-func NewSyslogTarget(filter logr.Filter, formatter logr.Formatter, params *SyslogParams, maxQueue int) (*Syslog, error) {
- writer, err := syslog.Dial(params.Network, params.Raddr, params.Priority, params.Tag)
- if err != nil {
- return nil, err
- }
-
- s := &Syslog{w: writer}
- s.Basic.Start(s, s, filter, formatter, maxQueue)
-
- return s, nil
-}
-
-// Shutdown stops processing log records after making best
-// effort to flush queue.
-func (s *Syslog) Shutdown(ctx context.Context) error {
- errs := merror.New()
-
- err := s.Basic.Shutdown(ctx)
- errs.Append(err)
-
- err = s.w.Close()
- errs.Append(err)
-
- return errs.ErrorOrNil()
-}
-
-// Write converts the log record to bytes, via the Formatter,
-// and outputs to syslog.
-func (s *Syslog) Write(rec *logr.LogRec) error {
- _, stacktrace := s.IsLevelEnabled(rec.Level())
-
- buf := rec.Logger().Logr().BorrowBuffer()
- defer rec.Logger().Logr().ReleaseBuffer(buf)
-
- buf, err := s.Formatter().Format(rec, stacktrace, buf)
- if err != nil {
- return err
- }
- txt := buf.String()
-
- switch rec.Level() {
- case logr.Panic, logr.Fatal:
- err = s.w.Crit(txt)
- case logr.Error:
- err = s.w.Err(txt)
- case logr.Warn:
- err = s.w.Warning(txt)
- case logr.Debug, logr.Trace:
- err = s.w.Debug(txt)
- default:
- // logr.Info plus all custom levels.
- err = s.w.Info(txt)
- }
-
- if err != nil {
- reporter := rec.Logger().Logr().ReportError
- reporter(fmt.Errorf("syslog write fail: %w", err))
- // syslog writer will try to reconnect.
- }
- return err
-}
diff --git a/vendor/github.com/mattermost/logr/target/writer.go b/vendor/github.com/mattermost/logr/target/writer.go
deleted file mode 100644
index 2250da5138..0000000000
--- a/vendor/github.com/mattermost/logr/target/writer.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package target
-
-import (
- "io"
- "io/ioutil"
-
- "github.com/mattermost/logr"
-)
-
-// Writer outputs log records to any `io.Writer`.
-type Writer struct {
- logr.Basic
- out io.Writer
-}
-
-// NewWriterTarget creates a target capable of outputting log records to an io.Writer.
-func NewWriterTarget(filter logr.Filter, formatter logr.Formatter, out io.Writer, maxQueue int) *Writer {
- if out == nil {
- out = ioutil.Discard
- }
- w := &Writer{out: out}
- w.Basic.Start(w, w, filter, formatter, maxQueue)
- return w
-}
-
-// Write converts the log record to bytes, via the Formatter,
-// and outputs to the io.Writer.
-func (w *Writer) Write(rec *logr.LogRec) error {
- _, stacktrace := w.IsLevelEnabled(rec.Level())
-
- buf := rec.Logger().Logr().BorrowBuffer()
- defer rec.Logger().Logr().ReleaseBuffer(buf)
-
- buf, err := w.Formatter().Format(rec, stacktrace, buf)
- if err != nil {
- return err
- }
- _, err = w.out.Write(buf.Bytes())
- return err
-}
diff --git a/vendor/github.com/mattermost/logr/.gitignore b/vendor/github.com/mattermost/logr/v2/.gitignore
similarity index 96%
rename from vendor/github.com/mattermost/logr/.gitignore
rename to vendor/github.com/mattermost/logr/v2/.gitignore
index c2c0a9e2e5..bac5e1c16a 100644
--- a/vendor/github.com/mattermost/logr/.gitignore
+++ b/vendor/github.com/mattermost/logr/v2/.gitignore
@@ -34,3 +34,4 @@ logs
# test apps
test/cmd/testapp1/testapp1
test/cmd/simple/simple
+test/cmd/gelf/gelf
diff --git a/vendor/github.com/mattermost/logr/.travis.yml b/vendor/github.com/mattermost/logr/v2/.travis.yml
similarity index 100%
rename from vendor/github.com/mattermost/logr/.travis.yml
rename to vendor/github.com/mattermost/logr/v2/.travis.yml
diff --git a/vendor/github.com/mattermost/logr/LICENSE b/vendor/github.com/mattermost/logr/v2/LICENSE
similarity index 100%
rename from vendor/github.com/mattermost/logr/LICENSE
rename to vendor/github.com/mattermost/logr/v2/LICENSE
diff --git a/vendor/github.com/mattermost/logr/README.md b/vendor/github.com/mattermost/logr/v2/README.md
similarity index 83%
rename from vendor/github.com/mattermost/logr/README.md
rename to vendor/github.com/mattermost/logr/v2/README.md
index a25d6de0a2..9ee0f17c37 100644
--- a/vendor/github.com/mattermost/logr/README.md
+++ b/vendor/github.com/mattermost/logr/v2/README.md
@@ -16,9 +16,9 @@ It is very much inspired by [Logrus](https://github.com/sirupsen/logrus) but add
| entity | description |
| ------ | ----------- |
-| Logr | Engine instance typically instantiated once; used to configure logging.
```lgr := &Logr{}```|
+| Logr | Engine instance typically instantiated once; used to configure logging.
```lgr,_ := logr.New()```|
| Logger | Provides contextual logging via fields; lightweight, can be created once and accessed globally or create on demand.
```logger := lgr.NewLogger()```
```logger2 := logger.WithField("user", "Sam")```|
-| Target | A destination for log items such as console, file, database or just about anything that can be written to. Each target has its own filter/level and formatter, and any number of targets can be added to a Logr. Targets for syslog and any io.Writer are built-in and it is easy to create your own. You can also use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) via a simple [adapter](https://github.com/wiggin77/logrus4logr).|
+| Target | A destination for log items such as console, file, database or just about anything that can be written to. Each target has its own filter/level and formatter, and any number of targets can be added to a Logr. Targets for file, syslog and any io.Writer are built-in and it is easy to create your own. You can also use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) via a simple [adapter](https://github.com/wiggin77/logrus4logr).|
| Filter | Determines which logging calls get written versus filtered out. Also determines which logging calls generate a stack trace.
```filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Fatal}```|
| Formatter | Formats the output. Logr includes built-in formatters for JSON and plain text with delimiters. It is easy to create your own formatters or you can also use any [Logrus formatters](https://github.com/sirupsen/logrus#formatters) via a simple [adapter](https://github.com/wiggin77/logrus4logr).
```formatter := &format.Plain{Delim: " \| "}```|
@@ -26,15 +26,15 @@ It is very much inspired by [Logrus](https://github.com/sirupsen/logrus) but add
```go
// Create Logr instance.
-lgr := &logr.Logr{}
+lgr,_ := logr.New()
// Create a filter and formatter. Both can be shared by multiple
// targets.
filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Error}
-formatter := &format.Plain{Delim: " | "}
+formatter := &formatters.Plain{Delim: " | "}
// WriterTarget outputs to any io.Writer
-t := target.NewWriterTarget(filter, formatter, os.StdOut, 1000)
+t := targets.NewWriterTarget(filter, formatter, os.StdOut, 1000)
lgr.AddTarget(t)
// One or more Loggers can be created, shared, used concurrently,
@@ -56,7 +56,7 @@ Fields allow for contextual logging, meaning information can be added to log sta
Fields are added via Loggers:
```go
-lgr := &Logr{}
+lgr,_ := logr.New()
// ... add targets ...
logger := lgr.NewLogger().WithFields(logr.Fields{
"user": user,
@@ -88,14 +88,14 @@ Logr also supports custom filters (logr.CustomFilter) which allow fine grained i
LoginLevel := logr.Level{ID: 100, Name: "login ", Stacktrace: false}
LogoutLevel := logr.Level{ID: 101, Name: "logout", Stacktrace: false}
- lgr := &logr.Logr{}
+ lgr,_ := logr.New()
// create a custom filter with custom levels.
filter := &logr.CustomFilter{}
filter.Add(LoginLevel, LogoutLevel)
- formatter := &format.Plain{Delim: " | "}
- tgr := target.NewWriterTarget(filter, formatter, os.StdOut, 1000)
+ formatter := &formatters.Plain{Delim: " | "}
+ tgr := targets.NewWriterTarget(filter, formatter, os.StdOut, 1000)
lgr.AddTarget(tgr)
logger := lgr.NewLogger().WithFields(logr.Fields{"user": "Bob", "role": "admin"})
@@ -113,36 +113,31 @@ You can use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) vi
You can create your own target by implementing the [Target](./target.go) interface.
-An easier method is to use the [logr.Basic](./target.go) type target and build your functionality on that. Basic handles all the queuing and other plumbing so you only need to implement two methods. Example target that outputs to `io.Writer`:
+Example target that outputs to `io.Writer`:
```go
type Writer struct {
- logr.Basic
out io.Writer
}
-func NewWriterTarget(filter logr.Filter, formatter logr.Formatter, out io.Writer, maxQueue int) *Writer {
+func NewWriterTarget(out io.Writer) *Writer {
w := &Writer{out: out}
- w.Basic.Start(w, w, filter, formatter, maxQueue)
return w
}
+// Called once to initialize target.
+func (w *Writer) Init() error {
+ return nil
+}
+
// Write will always be called by a single goroutine, so no locking needed.
-// Just convert a log record to a []byte using the formatter and output the
-// bytes to your sink.
-func (w *Writer) Write(rec *logr.LogRec) error {
- _, stacktrace := w.IsLevelEnabled(rec.Level())
+func (w *Writer) Write(p []byte, rec *logr.LogRec) (int, error) {
+ return w.out.Write(buf.Bytes())
+}
- // take a buffer from the pool to avoid allocations or just allocate a new one.
- buf := rec.Logger().Logr().BorrowBuffer()
- defer rec.Logger().Logr().ReleaseBuffer(buf)
-
- buf, err := w.Formatter().Format(rec, stacktrace, buf)
- if err != nil {
- return err
- }
- _, err = w.out.Write(buf.Bytes())
- return err
+// Called once to cleanup/free resources for target.
+func (w *Writer) Shutdown() error {
+ return nil
}
```
diff --git a/vendor/github.com/mattermost/logr/v2/config/config.go b/vendor/github.com/mattermost/logr/v2/config/config.go
new file mode 100644
index 0000000000..a93b7a25a2
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/config/config.go
@@ -0,0 +1,209 @@
+package config
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/mattermost/logr/v2"
+ "github.com/mattermost/logr/v2/formatters"
+ "github.com/mattermost/logr/v2/targets"
+)
+
+type TargetCfg struct {
+ Type string `json:"type"` // one of "console", "file", "tcp", "syslog", "none".
+ Options json.RawMessage `json:"options,omitempty"`
+ Format string `json:"format"` // one of "json", "plain", "gelf"
+ FormatOptions json.RawMessage `json:"format_options,omitempty"`
+ Levels []logr.Level `json:"levels"`
+ MaxQueueSize int `json:"maxqueuesize,omitempty"`
+}
+
+type ConsoleOptions struct {
+ Out string `json:"out"` // one of "stdout", "stderr"
+}
+
+type TargetFactory func(targetType string, options json.RawMessage) (logr.Target, error)
+type FormatterFactory func(format string, options json.RawMessage) (logr.Formatter, error)
+
+type Factories struct {
+ targetFactory TargetFactory // can be nil
+ formatterFactory FormatterFactory // can be nil
+}
+
+var removeAll = func(ti logr.TargetInfo) bool { return true }
+
+// ConfigureTargets replaces the current list of log targets with a new one based on a map
+// of name->TargetCfg. The map of TargetCfg's would typically be serialized from a JSON
+// source or can be programmatically created.
+//
+// An optional set of factories can be provided which will be called to create any target
+// types or formatters not built-in.
+//
+// To append log targets to an existing config, use `(*Logr).AddTarget` or
+// `(*Logr).AddTargetFromConfig` instead.
+func ConfigureTargets(lgr *logr.Logr, config map[string]TargetCfg, factories *Factories) error {
+ if err := lgr.RemoveTargets(context.Background(), removeAll); err != nil {
+ return fmt.Errorf("error removing existing log targets: %w", err)
+ }
+
+ if factories == nil {
+ factories = &Factories{nil, nil}
+ }
+
+ for name, tcfg := range config {
+ target, err := newTarget(tcfg.Type, tcfg.Options, factories.targetFactory)
+ if err != nil {
+ return fmt.Errorf("error creating log target %s: %w", name, err)
+ }
+
+ if target == nil {
+ continue
+ }
+
+ formatter, err := newFormatter(tcfg.Format, tcfg.FormatOptions, factories.formatterFactory)
+ if err != nil {
+ return fmt.Errorf("error creating formatter for log target %s: %w", name, err)
+ }
+
+ filter := newFilter(tcfg.Levels)
+ qSize := tcfg.MaxQueueSize
+ if qSize == 0 {
+ qSize = logr.DefaultMaxQueueSize
+ }
+
+ if err = lgr.AddTarget(target, name, filter, formatter, qSize); err != nil {
+ return fmt.Errorf("error adding log target %s: %w", name, err)
+ }
+ }
+ return nil
+}
+
+func newFilter(levels []logr.Level) logr.Filter {
+ filter := &logr.CustomFilter{}
+ for _, lvl := range levels {
+ filter.Add(lvl)
+ }
+ return filter
+}
+
+func newTarget(targetType string, options json.RawMessage, factory TargetFactory) (logr.Target, error) {
+ switch strings.ToLower(targetType) {
+ case "console":
+ c := ConsoleOptions{}
+ if len(options) != 0 {
+ if err := json.Unmarshal(options, &c); err != nil {
+ return nil, fmt.Errorf("error decoding console target options: %w", err)
+ }
+ }
+ var w io.Writer
+ switch c.Out {
+ case "stderr":
+ w = os.Stderr
+ case "stdout", "":
+ w = os.Stdout
+ default:
+ return nil, fmt.Errorf("invalid console target option '%s'", c.Out)
+ }
+ return targets.NewWriterTarget(w), nil
+ case "file":
+ fo := targets.FileOptions{}
+ if len(options) == 0 {
+ return nil, errors.New("missing file target options")
+ }
+ if err := json.Unmarshal(options, &fo); err != nil {
+ return nil, fmt.Errorf("error decoding file target options: %w", err)
+ }
+ if err := fo.CheckValid(); err != nil {
+ return nil, fmt.Errorf("invalid file target options: %w", err)
+ }
+ return targets.NewFileTarget(fo), nil
+ case "tcp":
+ to := targets.TcpOptions{}
+ if len(options) == 0 {
+ return nil, errors.New("missing TCP target options")
+ }
+ if err := json.Unmarshal(options, &to); err != nil {
+ return nil, fmt.Errorf("error decoding TCP target options: %w", err)
+ }
+ if err := to.CheckValid(); err != nil {
+ return nil, fmt.Errorf("invalid TCP target options: %w", err)
+ }
+ return targets.NewTcpTarget(&to), nil
+ case "syslog":
+ so := targets.SyslogOptions{}
+ if len(options) == 0 {
+ return nil, errors.New("missing SysLog target options")
+ }
+ if err := json.Unmarshal(options, &so); err != nil {
+ return nil, fmt.Errorf("error decoding Syslog target options: %w", err)
+ }
+ if err := so.CheckValid(); err != nil {
+ return nil, fmt.Errorf("invalid SysLog target options: %w", err)
+ }
+ return targets.NewSyslogTarget(&so)
+ case "none":
+ return nil, nil
+ default:
+ if factory != nil {
+ t, err := factory(targetType, options)
+ if err != nil || t == nil {
+ return nil, fmt.Errorf("error from target factory: %w", err)
+ }
+ return t, nil
+ }
+ }
+ return nil, fmt.Errorf("target type '%s' is unrecogized", targetType)
+}
+
+func newFormatter(format string, options json.RawMessage, factory FormatterFactory) (logr.Formatter, error) {
+ switch strings.ToLower(format) {
+ case "json":
+ j := formatters.JSON{}
+ if len(options) != 0 {
+ if err := json.Unmarshal(options, &j); err != nil {
+ return nil, fmt.Errorf("error decoding JSON formatter options: %w", err)
+ }
+ if err := j.CheckValid(); err != nil {
+ return nil, fmt.Errorf("invalid JSON formatter options: %w", err)
+ }
+ }
+ return &j, nil
+ case "plain":
+ p := formatters.Plain{}
+ if len(options) != 0 {
+ if err := json.Unmarshal(options, &p); err != nil {
+ return nil, fmt.Errorf("error decoding Plain formatter options: %w", err)
+ }
+ if err := p.CheckValid(); err != nil {
+ return nil, fmt.Errorf("invalid plain formatter options: %w", err)
+ }
+ }
+ return &p, nil
+ case "gelf":
+ g := formatters.Gelf{}
+ if len(options) != 0 {
+ if err := json.Unmarshal(options, &g); err != nil {
+ return nil, fmt.Errorf("error decoding Gelf formatter options: %w", err)
+ }
+ if err := g.CheckValid(); err != nil {
+ return nil, fmt.Errorf("invalid GELF formatter options: %w", err)
+ }
+ }
+ return &g, nil
+
+ default:
+ if factory != nil {
+ f, err := factory(format, options)
+ if err != nil || f == nil {
+ return nil, fmt.Errorf("error from formatter factory: %w", err)
+ }
+ return f, nil
+ }
+ }
+ return nil, fmt.Errorf("format '%s' is unrecogized", format)
+}
diff --git a/vendor/github.com/mattermost/logr/v2/config/sample-config.json b/vendor/github.com/mattermost/logr/v2/config/sample-config.json
new file mode 100644
index 0000000000..540bafbb8d
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/config/sample-config.json
@@ -0,0 +1,90 @@
+{
+ "sample-console": {
+ "type": "console",
+ "options": {
+ "out": "stdout"
+ },
+ "format": "plain",
+ "format_options": {
+ "delim": " | "
+ },
+ "levels": [
+ {"id": 5, "name": "debug"},
+ {"id": 4, "name": "info"},
+ {"id": 3, "name": "warn"},
+ {"id": 2, "name": "error", "stacktrace": true},
+ {"id": 1, "name": "fatal", "stacktrace": true},
+ {"id": 0, "name": "panic", "stacktrace": true}
+ ],
+ "maxqueuesize": 1000
+ },
+ "sample-file": {
+ "type": "file",
+ "options": {
+ "filename": "test.log",
+ "max_size": 1000000,
+ "max_age": 1,
+ "max_backups": 10,
+ "compress": true
+ },
+ "format": "json",
+ "format_options": {
+ },
+ "levels": [
+ {"id": 5, "name": "debug"},
+ {"id": 4, "name": "info"},
+ {"id": 3, "name": "warn"},
+ {"id": 2, "name": "error", "stacktrace": true},
+ {"id": 1, "name": "fatal", "stacktrace": true},
+ {"id": 0, "name": "panic", "stacktrace": true}
+ ],
+ "maxqueuesize": 1000
+ },
+ "sample-tcp": {
+ "type": "tcp",
+ "options": {
+ "host": "localhost",
+ "port": 18066,
+ "tls": false,
+ "cert": "",
+ "insecure": false
+ },
+ "format": "gelf",
+ "format_options": {
+ "hostname": "server01"
+ },
+ "levels": [
+ {"id": 5, "name": "debug"},
+ {"id": 4, "name": "info"},
+ {"id": 3, "name": "warn"},
+ {"id": 2, "name": "error", "stacktrace": true},
+ {"id": 1, "name": "fatal", "stacktrace": true},
+ {"id": 0, "name": "panic", "stacktrace": true}
+ ],
+ "maxqueuesize": 1000
+ },
+ "sample-syslog": {
+ "type": "syslog",
+ "options": {
+ "host": "localhost",
+ "port": 18066,
+ "tls": false,
+ "cert": "",
+ "insecure": false,
+ "tag": "testapp"
+ },
+ "format": "plain",
+ "format_options": {
+ "delim": " "
+ },
+ "levels": [
+ {"id": 5, "name": "debug"},
+ {"id": 4, "name": "info"},
+ {"id": 3, "name": "warn"},
+ {"id": 2, "name": "error", "stacktrace": true},
+ {"id": 1, "name": "fatal", "stacktrace": true},
+ {"id": 0, "name": "panic", "stacktrace": true}
+ ],
+ "maxqueuesize": 1000
+ }
+}
diff --git a/vendor/github.com/mattermost/logr/const.go b/vendor/github.com/mattermost/logr/v2/const.go
similarity index 98%
rename from vendor/github.com/mattermost/logr/const.go
rename to vendor/github.com/mattermost/logr/v2/const.go
index 704d050756..29d9224112 100644
--- a/vendor/github.com/mattermost/logr/const.go
+++ b/vendor/github.com/mattermost/logr/v2/const.go
@@ -13,7 +13,7 @@ const (
// MaxLevelID is the maximum value of a level ID. Some level cache implementations will
// allocate a cache of this size. Cannot exceed uint.
- MaxLevelID = 256
+ MaxLevelID = 65535
// DefaultEnqueueTimeout is the default amount of time a log record can take to be queued.
// This only applies to blocking enqueue which happen after `logr.OnQueueFull` is called
diff --git a/vendor/github.com/mattermost/logr/v2/field.go b/vendor/github.com/mattermost/logr/v2/field.go
new file mode 100644
index 0000000000..5725d0a10e
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/field.go
@@ -0,0 +1,403 @@
+package logr
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+var (
+ Comma = []byte{','}
+ Equals = []byte{'='}
+ Space = []byte{' '}
+ Newline = []byte{'\n'}
+ Quote = []byte{'"'}
+ Colon = []byte{'"'}
+)
+
+// LogCloner is implemented by `Any` types that require a clone to be provided
+// to the logger because the original may mutate.
+type LogCloner interface {
+ LogClone() interface{}
+}
+
+// LogWriter is implemented by `Any` types that provide custom formatting for
+// log output. A string representation of the type should be written directly to
+// the `io.Writer`.
+type LogWriter interface {
+ LogWrite(w io.Writer) error
+}
+
+type FieldType uint8
+
+const (
+ UnknownType FieldType = iota
+ StringType
+ StringerType
+ StructType
+ ErrorType
+ BoolType
+ TimestampMillisType
+ TimeType
+ DurationType
+ Int64Type
+ Int32Type
+ IntType
+ Uint64Type
+ Uint32Type
+ UintType
+ Float64Type
+ Float32Type
+ BinaryType
+ ArrayType
+ MapType
+)
+
+type Field struct {
+ Key string
+ Type FieldType
+ Integer int64
+ Float float64
+ String string
+ Interface interface{}
+}
+
+func quoteString(w io.Writer, s string, shouldQuote func(s string) bool) error {
+ b := shouldQuote(s)
+ if b {
+ if _, err := w.Write(Quote); err != nil {
+ return err
+ }
+ }
+
+ if _, err := w.Write([]byte(s)); err != nil {
+ return err
+ }
+
+ if b {
+ if _, err := w.Write(Quote); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// ValueString converts a known type to a string using default formatting.
+// This is called lazily by a formatter.
+// Formatters can provide custom formatting or types passed via `Any` can implement
+// the `LogString` interface to generate output for logging.
+// If the optional shouldQuote callback is provided, then it will be called for any
+// string output that could potentially need to be quoted.
+func (f Field) ValueString(w io.Writer, shouldQuote func(s string) bool) error {
+ if shouldQuote == nil {
+ shouldQuote = func(s string) bool { return false }
+ }
+ var err error
+ switch f.Type {
+ case StringType:
+ err = quoteString(w, f.String, shouldQuote)
+
+ case StringerType:
+ s, ok := f.Interface.(fmt.Stringer)
+ if ok {
+ err = quoteString(w, s.String(), shouldQuote)
+ } else if f.Interface == nil {
+ err = quoteString(w, "", shouldQuote)
+ } else {
+ err = fmt.Errorf("invalid fmt.Stringer for key %s", f.Key)
+ }
+
+ case StructType:
+ s, ok := f.Interface.(LogWriter)
+ if ok {
+ err = s.LogWrite(w)
+ break
+ }
+ // structs that do not implement LogWriter fall back to reflection via Printf.
+ // TODO: create custom reflection-based encoder.
+ _, err = fmt.Fprintf(w, "%v", f.Interface)
+
+ case ErrorType:
+ // TODO: create custom error encoder.
+ err = quoteString(w, fmt.Sprintf("%v", f.Interface), shouldQuote)
+
+ case BoolType:
+ var b bool
+ if f.Integer != 0 {
+ b = true
+ }
+ _, err = io.WriteString(w, strconv.FormatBool(b))
+
+ case TimestampMillisType:
+ ts := time.Unix(f.Integer/1000, (f.Integer%1000)*int64(time.Millisecond))
+ err = quoteString(w, ts.UTC().Format(TimestampMillisFormat), shouldQuote)
+
+ case TimeType:
+ t, ok := f.Interface.(time.Time)
+ if !ok {
+ err = errors.New("invalid time")
+ break
+ }
+ err = quoteString(w, t.Format(DefTimestampFormat), shouldQuote)
+
+ case DurationType:
+ _, err = fmt.Fprintf(w, "%s", time.Duration(f.Integer))
+
+ case Int64Type, Int32Type, IntType:
+ _, err = io.WriteString(w, strconv.FormatInt(f.Integer, 10))
+
+ case Uint64Type, Uint32Type, UintType:
+ _, err = io.WriteString(w, strconv.FormatUint(uint64(f.Integer), 10))
+
+ case Float64Type, Float32Type:
+ size := 64
+ if f.Type == Float32Type {
+ size = 32
+ }
+ err = quoteString(w, strconv.FormatFloat(f.Float, 'f', -1, size), shouldQuote)
+
+ case BinaryType:
+ b, ok := f.Interface.([]byte)
+ if ok {
+ _, err = fmt.Fprintf(w, "[%X]", b)
+ break
+ }
+ _, err = fmt.Fprintf(w, "[%v]", f.Interface)
+
+ case ArrayType:
+ a := reflect.ValueOf(f.Interface)
+ arr:
+ for i := 0; i < a.Len(); i++ {
+ item := a.Index(i)
+ switch v := item.Interface().(type) {
+ case LogWriter:
+ if err = v.LogWrite(w); err != nil {
+ break arr
+ }
+ case fmt.Stringer:
+ if err = quoteString(w, v.String(), shouldQuote); err != nil {
+ break arr
+ }
+ default:
+ s := fmt.Sprintf("%v", v)
+ if err = quoteString(w, s, shouldQuote); err != nil {
+ break arr
+ }
+ }
+ if _, err = w.Write(Comma); err != nil {
+ break arr
+ }
+ }
+
+ case MapType:
+ a := reflect.ValueOf(f.Interface)
+ iter := a.MapRange()
+ it:
+ for iter.Next() {
+ if _, err = io.WriteString(w, iter.Key().String()); err != nil {
+ break it
+ }
+ if _, err = w.Write(Equals); err != nil {
+ break it
+ }
+ val := iter.Value().Interface()
+ switch v := val.(type) {
+ case LogWriter:
+ if err = v.LogWrite(w); err != nil {
+ break it
+ }
+ case fmt.Stringer:
+ if err = quoteString(w, v.String(), shouldQuote); err != nil {
+ break it
+ }
+ default:
+ s := fmt.Sprintf("%v", v)
+ if err = quoteString(w, s, shouldQuote); err != nil {
+ break it
+ }
+ }
+ if _, err = w.Write(Comma); err != nil {
+ break it
+ }
+ }
+
+ case UnknownType:
+ _, err = fmt.Fprintf(w, "%v", f.Interface)
+
+ default:
+ err = fmt.Errorf("invalid type %d", f.Type)
+ }
+ return err
+}
+
+func nilField(key string) Field {
+ return String(key, "")
+}
+
+func fieldForAny(key string, val interface{}) Field {
+ switch v := val.(type) {
+ case LogCloner:
+ if v == nil {
+ return nilField(key)
+ }
+ c := v.LogClone()
+ return Field{Key: key, Type: StructType, Interface: c}
+ case *LogCloner:
+ if v == nil {
+ return nilField(key)
+ }
+ c := (*v).LogClone()
+ return Field{Key: key, Type: StructType, Interface: c}
+ case LogWriter:
+ if v == nil {
+ return nilField(key)
+ }
+ return Field{Key: key, Type: StructType, Interface: v}
+ case *LogWriter:
+ if v == nil {
+ return nilField(key)
+ }
+ return Field{Key: key, Type: StructType, Interface: *v}
+ case bool:
+ return Bool(key, v)
+ case *bool:
+ if v == nil {
+ return nilField(key)
+ }
+ return Bool(key, *v)
+ case float64:
+ return Float64(key, v)
+ case *float64:
+ if v == nil {
+ return nilField(key)
+ }
+ return Float64(key, *v)
+ case float32:
+ return Float32(key, v)
+ case *float32:
+ if v == nil {
+ return nilField(key)
+ }
+ return Float32(key, *v)
+ case int:
+ return Int(key, v)
+ case *int:
+ if v == nil {
+ return nilField(key)
+ }
+ return Int(key, *v)
+ case int64:
+ return Int64(key, v)
+ case *int64:
+ if v == nil {
+ return nilField(key)
+ }
+ return Int64(key, *v)
+ case int32:
+ return Int32(key, v)
+ case *int32:
+ if v == nil {
+ return nilField(key)
+ }
+ return Int32(key, *v)
+ case int16:
+ return Int32(key, int32(v))
+ case *int16:
+ if v == nil {
+ return nilField(key)
+ }
+ return Int32(key, int32(*v))
+ case int8:
+ return Int32(key, int32(v))
+ case *int8:
+ if v == nil {
+ return nilField(key)
+ }
+ return Int32(key, int32(*v))
+ case string:
+ return String(key, v)
+ case *string:
+ if v == nil {
+ return nilField(key)
+ }
+ return String(key, *v)
+ case uint:
+ return Uint(key, v)
+ case *uint:
+ if v == nil {
+ return nilField(key)
+ }
+ return Uint(key, *v)
+ case uint64:
+ return Uint64(key, v)
+ case *uint64:
+ if v == nil {
+ return nilField(key)
+ }
+ return Uint64(key, *v)
+ case uint32:
+ return Uint32(key, v)
+ case *uint32:
+ if v == nil {
+ return nilField(key)
+ }
+ return Uint32(key, *v)
+ case uint16:
+ return Uint32(key, uint32(v))
+ case *uint16:
+ if v == nil {
+ return nilField(key)
+ }
+ return Uint32(key, uint32(*v))
+ case uint8:
+ return Uint32(key, uint32(v))
+ case *uint8:
+ if v == nil {
+ return nilField(key)
+ }
+ return Uint32(key, uint32(*v))
+ case []byte:
+ if v == nil {
+ return nilField(key)
+ }
+ return Field{Key: key, Type: BinaryType, Interface: v}
+ case time.Time:
+ return Time(key, v)
+ case *time.Time:
+ if v == nil {
+ return nilField(key)
+ }
+ return Time(key, *v)
+ case time.Duration:
+ return Duration(key, v)
+ case *time.Duration:
+ if v == nil {
+ return nilField(key)
+ }
+ return Duration(key, *v)
+ case error:
+ return NamedErr(key, v)
+ case fmt.Stringer:
+ if v == nil {
+ return nilField(key)
+ }
+ return Field{Key: key, Type: StringerType, Interface: v}
+ case *fmt.Stringer:
+ if v == nil {
+ return nilField(key)
+ }
+ return Field{Key: key, Type: StringerType, Interface: *v}
+ default:
+ return Field{Key: key, Type: UnknownType, Interface: val}
+ }
+}
+
+// FieldSorter provides sorting of an array of fields by key.
+type FieldSorter []Field
+
+func (fs FieldSorter) Len() int { return len(fs) }
+func (fs FieldSorter) Less(i, j int) bool { return fs[i].Key < fs[j].Key }
+func (fs FieldSorter) Swap(i, j int) { fs[i], fs[j] = fs[j], fs[i] }
diff --git a/vendor/github.com/mattermost/logr/v2/fieldapi.go b/vendor/github.com/mattermost/logr/v2/fieldapi.go
new file mode 100644
index 0000000000..58b12280f2
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/fieldapi.go
@@ -0,0 +1,110 @@
+package logr
+
+import (
+ "fmt"
+ "time"
+)
+
+// 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.
+func Any(key string, val interface{}) Field {
+ return fieldForAny(key, val)
+}
+
+// Int64 constructs a field containing a key and Int64 value.
+func Int64(key string, val int64) Field {
+ return Field{Key: key, Type: Int64Type, Integer: val}
+}
+
+// Int32 constructs a field containing a key and Int32 value.
+func Int32(key string, val int32) Field {
+ return Field{Key: key, Type: Int32Type, Integer: int64(val)}
+}
+
+// Int constructs a field containing a key and Int value.
+func Int(key string, val int) Field {
+ return Field{Key: key, Type: IntType, Integer: int64(val)}
+}
+
+// Uint64 constructs a field containing a key and Uint64 value.
+func Uint64(key string, val uint64) Field {
+ return Field{Key: key, Type: Uint64Type, Integer: int64(val)}
+}
+
+// Uint32 constructs a field containing a key and Uint32 value.
+func Uint32(key string, val uint32) Field {
+ return Field{Key: key, Type: Uint32Type, Integer: int64(val)}
+}
+
+// Uint constructs a field containing a key and Uint value.
+func Uint(key string, val uint) Field {
+ return Field{Key: key, Type: UintType, Integer: int64(val)}
+}
+
+// Float64 constructs a field containing a key and Float64 value.
+func Float64(key string, val float64) Field {
+ return Field{Key: key, Type: Float64Type, Float: val}
+}
+
+// Float32 constructs a field containing a key and Float32 value.
+func Float32(key string, val float32) Field {
+ return Field{Key: key, Type: Float32Type, Float: float64(val)}
+}
+
+// String constructs a field containing a key and String value.
+func String(key string, val string) Field {
+ return Field{Key: key, Type: StringType, String: val}
+}
+
+// Stringer constructs a field containing a key and a `fmt.Stringer` value.
+// The `String` method will be called in lazy fashion.
+func Stringer(key string, val fmt.Stringer) Field {
+ return Field{Key: key, Type: StringerType, Interface: val}
+}
+
+// Err constructs a field containing a default key ("error") and error value.
+func Err(err error) Field {
+ return NamedErr("error", err)
+}
+
+// NamedErr constructs a field containing a key and error value.
+func NamedErr(key string, err error) Field {
+ return Field{Key: key, Type: ErrorType, Interface: err}
+}
+
+// Bool constructs a field containing a key and bool value.
+func Bool(key string, val bool) Field {
+ var b int64
+ if val {
+ b = 1
+ }
+ return Field{Key: key, Type: BoolType, Integer: b}
+}
+
+// Time constructs a field containing a key and time.Time value.
+func Time(key string, val time.Time) Field {
+ return Field{Key: key, Type: TimeType, Interface: val}
+}
+
+// Duration constructs a field containing a key and time.Duration value.
+func Duration(key string, val time.Duration) Field {
+ return Field{Key: key, Type: DurationType, Integer: int64(val)}
+}
+
+// Millis constructs a field containing a key and timestamp value.
+// The timestamp is expected to be milliseconds since Jan 1, 1970 UTC.
+func Millis(key string, val int64) Field {
+ return Field{Key: key, Type: TimestampMillisType, Integer: val}
+}
+
+// Array constructs a field containing a key and array value.
+func Array(key string, val interface{}) Field {
+ return Field{Key: key, Type: ArrayType, Interface: val}
+}
+
+// Map constructs a field containing a key and map value.
+func Map(key string, val interface{}) Field {
+ return Field{Key: key, Type: MapType, Interface: val}
+}
diff --git a/vendor/github.com/mattermost/logr/v2/filter.go b/vendor/github.com/mattermost/logr/v2/filter.go
new file mode 100644
index 0000000000..a52a7cf4a5
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/filter.go
@@ -0,0 +1,10 @@
+package logr
+
+// Filter allows targets to determine which Level(s) are active
+// for logging and which Level(s) require a stack trace to be output.
+// A default implementation using "panic, fatal..." is provided, and
+// a more flexible alternative implementation is also provided that
+// allows any number of custom levels.
+type Filter interface {
+ GetEnabledLevel(level Level) (Level, bool)
+}
diff --git a/vendor/github.com/mattermost/logr/v2/filtercustom.go b/vendor/github.com/mattermost/logr/v2/filtercustom.go
new file mode 100644
index 0000000000..c20f2811b2
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/filtercustom.go
@@ -0,0 +1,47 @@
+package logr
+
+import (
+ "sync"
+)
+
+// CustomFilter allows targets to enable logging via a list of discrete levels.
+type CustomFilter struct {
+ mux sync.RWMutex
+ levels map[LevelID]Level
+}
+
+// NewCustomFilter creates a filter supporting discrete log levels.
+func NewCustomFilter(levels ...Level) *CustomFilter {
+ filter := &CustomFilter{}
+ filter.Add(levels...)
+ return filter
+}
+
+// GetEnabledLevel returns the Level with the specified Level.ID and whether the level
+// is enabled for this filter.
+func (cf *CustomFilter) GetEnabledLevel(level Level) (Level, bool) {
+ cf.mux.RLock()
+ defer cf.mux.RUnlock()
+ levelEnabled, ok := cf.levels[level.ID]
+
+ if ok && levelEnabled.Name == "" {
+ levelEnabled.Name = level.Name
+ }
+
+ return levelEnabled, ok
+}
+
+// Add adds one or more levels to the list. Adding a level enables logging for
+// that level on any targets using this CustomFilter.
+func (cf *CustomFilter) Add(levels ...Level) {
+ cf.mux.Lock()
+ defer cf.mux.Unlock()
+
+ if cf.levels == nil {
+ cf.levels = make(map[LevelID]Level)
+ }
+
+ for _, s := range levels {
+ cf.levels[s.ID] = s
+ }
+}
diff --git a/vendor/github.com/mattermost/logr/v2/filterstd.go b/vendor/github.com/mattermost/logr/v2/filterstd.go
new file mode 100644
index 0000000000..7f38a33228
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/filterstd.go
@@ -0,0 +1,65 @@
+package logr
+
+// StdFilter allows targets to filter via classic log levels where any level
+// beyond a certain verbosity/severity is enabled.
+type StdFilter struct {
+ Lvl Level
+ Stacktrace Level
+}
+
+// GetEnabledLevel returns the Level with the specified Level.ID and whether the level
+// is enabled for this filter.
+func (lt StdFilter) GetEnabledLevel(level Level) (Level, bool) {
+ enabled := level.ID <= lt.Lvl.ID
+ var levelEnabled Level
+
+ if enabled {
+ switch level.ID {
+ case Panic.ID:
+ levelEnabled = Panic
+ case Fatal.ID:
+ levelEnabled = Fatal
+ case Error.ID:
+ levelEnabled = Error
+ case Warn.ID:
+ levelEnabled = Warn
+ case Info.ID:
+ levelEnabled = Info
+ case Debug.ID:
+ levelEnabled = Debug
+ case Trace.ID:
+ levelEnabled = Trace
+ default:
+ levelEnabled = level
+ }
+ }
+ return levelEnabled, enabled
+}
+
+// IsEnabled returns true if the specified Level is at or above this verbosity. Also
+// determines if a stack trace is required.
+func (lt StdFilter) IsEnabled(level Level) bool {
+ return level.ID <= lt.Lvl.ID
+}
+
+// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
+func (lt StdFilter) IsStacktraceEnabled(level Level) bool {
+ return level.ID <= lt.Stacktrace.ID
+}
+
+var (
+ // Panic is the highest level of severity.
+ Panic = Level{ID: 0, Name: "panic", Color: Red}
+ // Fatal designates a catastrophic error.
+ Fatal = Level{ID: 1, Name: "fatal", Color: Red}
+ // Error designates a serious but possibly recoverable error.
+ Error = Level{ID: 2, Name: "error", Color: Red}
+ // Warn designates non-critical error.
+ Warn = Level{ID: 3, Name: "warn", Color: Yellow}
+ // Info designates information regarding application events.
+ Info = Level{ID: 4, Name: "info", Color: Cyan}
+ // Debug designates verbose information typically used for debugging.
+ Debug = Level{ID: 5, Name: "debug", Color: NoColor}
+ // Trace designates the highest verbosity of log output.
+ Trace = Level{ID: 6, Name: "trace", Color: NoColor}
+)
diff --git a/vendor/github.com/mattermost/logr/v2/formatter.go b/vendor/github.com/mattermost/logr/v2/formatter.go
new file mode 100644
index 0000000000..c8bb9b703d
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/formatter.go
@@ -0,0 +1,184 @@
+package logr
+
+import (
+ "bytes"
+ "io"
+ "runtime"
+ "strconv"
+)
+
+// Formatter turns a LogRec into a formatted string.
+type Formatter interface {
+ // IsStacktraceNeeded returns true if this formatter requires a stacktrace to be
+ // generated for each LogRecord. Enabling features such as `Caller` field require
+ // a stacktrace.
+ IsStacktraceNeeded() bool
+
+ // Format converts a log record to bytes. If buf is not nil then it will be
+ // be filled with the formatted results, otherwise a new buffer will be allocated.
+ Format(rec *LogRec, level Level, buf *bytes.Buffer) (*bytes.Buffer, error)
+}
+
+const (
+ // DefTimestampFormat is the default time stamp format used by Plain formatter and others.
+ DefTimestampFormat = "2006-01-02 15:04:05.000 Z07:00"
+
+ // TimestampMillisFormat is the format for logging milliseconds UTC
+ TimestampMillisFormat = "Jan _2 15:04:05.000"
+)
+
+type Writer struct {
+ io.Writer
+}
+
+func (w Writer) Writes(elems ...[]byte) (int, error) {
+ var count int
+ for _, e := range elems {
+ if c, err := w.Write(e); err != nil {
+ return count + c, err
+ } else {
+ count += c
+ }
+ }
+ return count, nil
+}
+
+// DefaultFormatter is the default formatter, outputting only text with
+// no colors and a space delimiter. Use `format.Plain` instead.
+type DefaultFormatter struct {
+}
+
+// IsStacktraceNeeded always returns false for default formatter since the
+// `Caller` field is not supported.
+func (p *DefaultFormatter) IsStacktraceNeeded() bool {
+ return false
+}
+
+// Format converts a log record to bytes.
+func (p *DefaultFormatter) Format(rec *LogRec, level Level, buf *bytes.Buffer) (*bytes.Buffer, error) {
+ if buf == nil {
+ buf = &bytes.Buffer{}
+ }
+ timestampFmt := DefTimestampFormat
+
+ buf.WriteString(rec.Time().Format(timestampFmt))
+ buf.Write(Space)
+
+ buf.WriteString(level.Name)
+ buf.Write(Space)
+
+ buf.WriteString(rec.Msg())
+ buf.Write(Space)
+
+ fields := rec.Fields()
+ if len(fields) > 0 {
+ if err := WriteFields(buf, fields, Space, NoColor); err != nil {
+ return nil, err
+ }
+ }
+
+ if level.Stacktrace {
+ frames := rec.StackFrames()
+ if len(frames) > 0 {
+ buf.Write(Newline)
+ if err := WriteStacktrace(buf, rec.StackFrames()); err != nil {
+ return nil, err
+ }
+ }
+ }
+ buf.Write(Newline)
+
+ return buf, nil
+}
+
+// WriteFields writes zero or more name value pairs to the io.Writer.
+// The pairs output in key=value format with optional separator between fields.
+func WriteFields(w io.Writer, fields []Field, separator []byte, color Color) error {
+ ws := Writer{w}
+
+ sep := []byte{}
+ for _, field := range fields {
+ if err := writeField(ws, field, sep, color); err != nil {
+ return err
+ }
+ sep = separator
+ }
+ return nil
+}
+
+func writeField(ws Writer, field Field, sep []byte, color Color) error {
+ if len(sep) != 0 {
+ if _, err := ws.Write(sep); err != nil {
+ return err
+ }
+ }
+ if err := WriteWithColor(ws, field.Key, color); err != nil {
+ return err
+ }
+ if _, err := ws.Write(Equals); err != nil {
+ return err
+ }
+ return field.ValueString(ws, shouldQuote)
+}
+
+// shouldQuote returns true if val contains any characters that might be unsafe
+// when injecting log output into an aggregator, viewer or report.
+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
+}
+
+// WriteStacktrace formats and outputs a stack trace to an io.Writer.
+func WriteStacktrace(w io.Writer, frames []runtime.Frame) error {
+ ws := Writer{w}
+ for _, frame := range frames {
+ if frame.Function != "" {
+ if _, err := ws.Writes(Space, Space, []byte(frame.Function), Newline); err != nil {
+ return err
+ }
+ }
+ if frame.File != "" {
+ s := strconv.FormatInt(int64(frame.Line), 10)
+ if _, err := ws.Writes([]byte{' ', ' ', ' ', ' ', ' ', ' '}, []byte(frame.File), Colon, []byte(s), Newline); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// WriteWithColor outputs a string with the specified ANSI color.
+func WriteWithColor(w io.Writer, s string, color Color) error {
+ var err error
+
+ writer := func(buf []byte) {
+ if err != nil {
+ return
+ }
+ _, err = w.Write(buf)
+ }
+
+ if color != NoColor {
+ writer(AnsiColorPrefix)
+ writer([]byte(strconv.FormatInt(int64(color), 10)))
+ writer(AnsiColorSuffix)
+ }
+
+ if err == nil {
+ _, err = io.WriteString(w, s)
+ }
+
+ if color != NoColor {
+ writer(AnsiColorPrefix)
+ writer([]byte(strconv.FormatInt(int64(NoColor), 10)))
+ writer(AnsiColorSuffix)
+ }
+ return err
+}
diff --git a/vendor/github.com/mattermost/logr/v2/formatters/gelf.go b/vendor/github.com/mattermost/logr/v2/formatters/gelf.go
new file mode 100644
index 0000000000..9dece13ca7
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/formatters/gelf.go
@@ -0,0 +1,152 @@
+package formatters
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "os"
+ "strings"
+
+ "github.com/francoispqt/gojay"
+ "github.com/mattermost/logr/v2"
+)
+
+const (
+ GelfVersion = "1.1"
+ GelfVersionKey = "version"
+ GelfHostKey = "host"
+ GelfShortKey = "short_message"
+ GelfFullKey = "full_message"
+ GelfTimestampKey = "timestamp"
+ GelfLevelKey = "level"
+)
+
+// Gelf formats log records as GELF rcords (https://docs.graylog.org/en/4.0/pages/gelf.html).
+type Gelf struct {
+ // Hostname allows a custom hostname, otherwise os.Hostname is used
+ Hostname string `json:"hostname"`
+
+ // EnableCaller enables output of the file and line number that emitted a log record.
+ EnableCaller bool `json:"enable_caller"`
+
+ // FieldSorter allows custom sorting for the context fields.
+ FieldSorter func(fields []logr.Field) []logr.Field `json:"-"`
+}
+
+func (g *Gelf) CheckValid() error {
+ return nil
+}
+
+// IsStacktraceNeeded returns true if a stacktrace is needed so we can output the `Caller` field.
+func (g *Gelf) IsStacktraceNeeded() bool {
+ return g.EnableCaller
+}
+
+// Format converts a log record to bytes in GELF format.
+func (g *Gelf) Format(rec *logr.LogRec, level logr.Level, buf *bytes.Buffer) (*bytes.Buffer, error) {
+ if buf == nil {
+ buf = &bytes.Buffer{}
+ }
+ enc := gojay.BorrowEncoder(buf)
+ defer func() {
+ enc.Release()
+ }()
+
+ gr := gelfRecord{
+ LogRec: rec,
+ Gelf: g,
+ level: level,
+ sorter: g.FieldSorter,
+ }
+
+ err := enc.EncodeObject(gr)
+ if err != nil {
+ return nil, err
+ }
+
+ buf.WriteByte(0)
+ return buf, nil
+}
+
+type gelfRecord struct {
+ *logr.LogRec
+ *Gelf
+ level logr.Level
+ sorter func(fields []logr.Field) []logr.Field
+}
+
+// MarshalJSONObject encodes the LogRec as JSON.
+func (gr gelfRecord) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.AddStringKey(GelfVersionKey, GelfVersion)
+ enc.AddStringKey(GelfHostKey, gr.getHostname())
+ enc.AddStringKey(GelfShortKey, gr.Msg())
+
+ if gr.level.Stacktrace {
+ frames := gr.StackFrames()
+ if len(frames) != 0 {
+ var sbuf strings.Builder
+ for _, frame := range frames {
+ fmt.Fprintf(&sbuf, "%s\n %s:%d\n", frame.Function, frame.File, frame.Line)
+ }
+ enc.AddStringKey(GelfFullKey, sbuf.String())
+ }
+ }
+
+ secs := float64(gr.Time().UTC().Unix())
+ millis := float64(gr.Time().Nanosecond() / 1000000)
+ ts := secs + (millis / 1000)
+ enc.AddFloat64Key(GelfTimestampKey, ts)
+
+ enc.AddUint32Key(GelfLevelKey, uint32(gr.level.ID))
+
+ var fields []logr.Field
+ if gr.EnableCaller {
+ caller := logr.Field{
+ Key: "_caller",
+ Type: logr.StringType,
+ String: gr.LogRec.Caller(),
+ }
+ fields = append(fields, caller)
+ }
+
+ fields = append(fields, gr.Fields()...)
+ if gr.sorter != nil {
+ fields = gr.sorter(fields)
+ }
+
+ if len(fields) > 0 {
+ for _, field := range fields {
+ if !strings.HasPrefix("_", field.Key) {
+ field.Key = "_" + field.Key
+ }
+ if err := encodeField(enc, field); err != nil {
+ enc.AddStringKey(field.Key, fmt.Sprintf("", err))
+ }
+ }
+ }
+}
+
+// IsNil returns true if the gelf record pointer is nil.
+func (gr gelfRecord) IsNil() bool {
+ return gr.LogRec == nil
+}
+
+func (g *Gelf) getHostname() string {
+ if g.Hostname != "" {
+ return g.Hostname
+ }
+ h, err := os.Hostname()
+ if err == nil {
+ return h
+ }
+
+ // get the egress IP by fake dialing any address. UDP ensures no dial.
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ return "unknown"
+ }
+ defer conn.Close()
+
+ local := conn.LocalAddr().(*net.UDPAddr)
+ return local.IP.String()
+}
diff --git a/vendor/github.com/mattermost/logr/v2/formatters/json.go b/vendor/github.com/mattermost/logr/v2/formatters/json.go
new file mode 100644
index 0000000000..172b9612dc
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/formatters/json.go
@@ -0,0 +1,273 @@
+package formatters
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "runtime"
+ "strings"
+ "sync"
+
+ "github.com/francoispqt/gojay"
+ "github.com/mattermost/logr/v2"
+)
+
+// JSON formats log records as JSON.
+type JSON struct {
+ // DisableTimestamp disables output of timestamp field.
+ DisableTimestamp bool `json:"disable_timestamp"`
+ // DisableLevel disables output of level field.
+ DisableLevel bool `json:"disable_level"`
+ // DisableMsg disables output of msg field.
+ DisableMsg bool `json:"disable_msg"`
+ // DisableFields disables output of all fields.
+ DisableFields bool `json:"disable_fields"`
+ // DisableStacktrace disables output of stack trace.
+ DisableStacktrace bool `json:"disable_stacktrace"`
+ // EnableCaller enables output of the file and line number that emitted a log record.
+ EnableCaller bool `json:"enable_caller"`
+
+ // TimestampFormat is an optional format for timestamps. If empty
+ // then DefTimestampFormat is used.
+ TimestampFormat string `json:"timestamp_format"`
+
+ // KeyTimestamp overrides the timestamp field key name.
+ KeyTimestamp string `json:"key_timestamp"`
+
+ // KeyLevel overrides the level field key name.
+ KeyLevel string `json:"key_level"`
+
+ // KeyMsg overrides the msg field key name.
+ KeyMsg string `json:"key_msg"`
+
+ // KeyGroupFields when not empty will group all context fields
+ // under this key.
+ KeyGroupFields string `json:"key_group_fields"`
+
+ // KeyStacktrace overrides the stacktrace field key name.
+ KeyStacktrace string `json:"key_stacktrace"`
+
+ // KeyCaller overrides the caller field key name.
+ KeyCaller string `json:"key_caller"`
+
+ // FieldSorter allows custom sorting of the fields. If nil then
+ // no sorting is done.
+ FieldSorter func(fields []logr.Field) []logr.Field `json:"-"`
+
+ once sync.Once
+}
+
+func (j *JSON) CheckValid() error {
+ return nil
+}
+
+// IsStacktraceNeeded returns true if a stacktrace is needed so we can output the `Caller` field.
+func (j *JSON) IsStacktraceNeeded() bool {
+ return j.EnableCaller
+}
+
+// Format converts a log record to bytes in JSON format.
+func (j *JSON) Format(rec *logr.LogRec, level logr.Level, buf *bytes.Buffer) (*bytes.Buffer, error) {
+ j.once.Do(j.applyDefaultKeyNames)
+
+ if buf == nil {
+ buf = &bytes.Buffer{}
+ }
+ enc := gojay.BorrowEncoder(buf)
+ defer func() {
+ enc.Release()
+ }()
+
+ jlr := JSONLogRec{
+ LogRec: rec,
+ JSON: j,
+ level: level,
+ sorter: j.FieldSorter,
+ }
+
+ err := enc.EncodeObject(jlr)
+ if err != nil {
+ return nil, err
+ }
+ buf.WriteByte('\n')
+ return buf, nil
+}
+
+func (j *JSON) applyDefaultKeyNames() {
+ if j.KeyTimestamp == "" {
+ j.KeyTimestamp = "timestamp"
+ }
+ if j.KeyLevel == "" {
+ j.KeyLevel = "level"
+ }
+ if j.KeyMsg == "" {
+ j.KeyMsg = "msg"
+ }
+ if j.KeyStacktrace == "" {
+ j.KeyStacktrace = "stacktrace"
+ }
+ if j.KeyCaller == "" {
+ j.KeyCaller = "caller"
+ }
+}
+
+// JSONLogRec decorates a LogRec adding JSON encoding.
+type JSONLogRec struct {
+ *logr.LogRec
+ *JSON
+ level logr.Level
+ sorter func(fields []logr.Field) []logr.Field
+}
+
+// MarshalJSONObject encodes the LogRec as JSON.
+func (jlr JSONLogRec) MarshalJSONObject(enc *gojay.Encoder) {
+ if !jlr.DisableTimestamp {
+ timestampFmt := jlr.TimestampFormat
+ if timestampFmt == "" {
+ timestampFmt = logr.DefTimestampFormat
+ }
+ time := jlr.Time()
+ enc.AddTimeKey(jlr.KeyTimestamp, &time, timestampFmt)
+ }
+ if !jlr.DisableLevel {
+ enc.AddStringKey(jlr.KeyLevel, jlr.level.Name)
+ }
+ if !jlr.DisableMsg {
+ enc.AddStringKey(jlr.KeyMsg, jlr.Msg())
+ }
+ if jlr.EnableCaller {
+ enc.AddStringKey(jlr.KeyCaller, jlr.Caller())
+ }
+ if !jlr.DisableFields {
+ fields := jlr.Fields()
+ if jlr.sorter != nil {
+ fields = jlr.sorter(fields)
+ }
+ if jlr.KeyGroupFields != "" {
+ enc.AddObjectKey(jlr.KeyGroupFields, FieldArray(fields))
+ } else {
+ if len(fields) > 0 {
+ for _, field := range fields {
+ field = jlr.prefixCollision(field)
+ if err := encodeField(enc, field); err != nil {
+ enc.AddStringKey(field.Key, "")
+ }
+ }
+ }
+ }
+ }
+ if jlr.level.Stacktrace && !jlr.DisableStacktrace {
+ frames := jlr.StackFrames()
+ if len(frames) > 0 {
+ enc.AddArrayKey(jlr.KeyStacktrace, stackFrames(frames))
+ }
+ }
+}
+
+// IsNil returns true if the LogRec pointer is nil.
+func (rec JSONLogRec) IsNil() bool {
+ return rec.LogRec == nil
+}
+
+func (rec JSONLogRec) prefixCollision(field logr.Field) logr.Field {
+ switch field.Key {
+ case rec.KeyTimestamp, rec.KeyLevel, rec.KeyMsg, rec.KeyStacktrace:
+ f := field
+ f.Key = "_" + field.Key
+ return rec.prefixCollision(f)
+ }
+ return field
+}
+
+type stackFrames []runtime.Frame
+
+// MarshalJSONArray encodes stackFrames slice as JSON.
+func (s stackFrames) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, frame := range s {
+ enc.AddObject(stackFrame(frame))
+ }
+}
+
+// IsNil returns true if stackFrames is empty slice.
+func (s stackFrames) IsNil() bool {
+ return len(s) == 0
+}
+
+type stackFrame runtime.Frame
+
+// MarshalJSONArray encodes stackFrame as JSON.
+func (f stackFrame) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.AddStringKey("Function", f.Function)
+ enc.AddStringKey("File", f.File)
+ enc.AddIntKey("Line", f.Line)
+}
+
+func (f stackFrame) IsNil() bool {
+ return false
+}
+
+type FieldArray []logr.Field
+
+// MarshalJSONObject encodes Fields map to JSON.
+func (fa FieldArray) MarshalJSONObject(enc *gojay.Encoder) {
+ for _, fld := range fa {
+ if err := encodeField(enc, fld); err != nil {
+ enc.AddStringKey(fld.Key, "")
+ }
+ }
+}
+
+// IsNil returns true if map is nil.
+func (fa FieldArray) IsNil() bool {
+ return fa == nil
+}
+
+func encodeField(enc *gojay.Encoder, field logr.Field) error {
+ // first check if the value has a marshaller already.
+ switch vt := field.Interface.(type) {
+ case gojay.MarshalerJSONObject:
+ enc.AddObjectKey(field.Key, vt)
+ return nil
+ case gojay.MarshalerJSONArray:
+ enc.AddArrayKey(field.Key, vt)
+ return nil
+ }
+
+ switch field.Type {
+ case logr.StringType:
+ enc.AddStringKey(field.Key, field.String)
+
+ case logr.BoolType:
+ var b bool
+ if field.Integer != 0 {
+ b = true
+ }
+ enc.AddBoolKey(field.Key, b)
+
+ case logr.StructType, logr.ArrayType, logr.MapType, logr.UnknownType:
+ b, err := json.Marshal(field.Interface)
+ if err != nil {
+ return err
+ }
+ embed := gojay.EmbeddedJSON(b)
+ enc.AddEmbeddedJSONKey(field.Key, &embed)
+
+ case logr.StringerType, logr.ErrorType, logr.TimestampMillisType, logr.TimeType, logr.DurationType, logr.BinaryType:
+ var buf strings.Builder
+ _ = field.ValueString(&buf, nil)
+ enc.AddStringKey(field.Key, buf.String())
+
+ case logr.Int64Type, logr.Int32Type, logr.IntType:
+ enc.AddInt64Key(field.Key, field.Integer)
+
+ case logr.Uint64Type, logr.Uint32Type, logr.UintType:
+ enc.AddUint64Key(field.Key, uint64(field.Integer))
+
+ case logr.Float64Type, logr.Float32Type:
+ enc.AddFloat64Key(field.Key, field.Float)
+
+ default:
+ return fmt.Errorf("invalid field type: %d", field.Type)
+ }
+ return nil
+}
diff --git a/vendor/github.com/mattermost/logr/v2/formatters/plain.go b/vendor/github.com/mattermost/logr/v2/formatters/plain.go
new file mode 100644
index 0000000000..4d8af643b9
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/formatters/plain.go
@@ -0,0 +1,146 @@
+package formatters
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+
+ "github.com/mattermost/logr/v2"
+)
+
+// Plain is the simplest formatter, outputting only text with
+// no colors.
+type Plain struct {
+ // DisableTimestamp disables output of timestamp field.
+ DisableTimestamp bool `json:"disable_timestamp"`
+ // DisableLevel disables output of level field.
+ DisableLevel bool `json:"disable_level"`
+ // DisableMsg disables output of msg field.
+ DisableMsg bool `json:"disable_msg"`
+ // DisableFields disables output of all fields.
+ DisableFields bool `json:"disable_fields"`
+ // DisableStacktrace disables output of stack trace.
+ DisableStacktrace bool `json:"disable_stacktrace"`
+ // EnableCaller enables output of the file and line number that emitted a log record.
+ EnableCaller bool `json:"enable_caller"`
+
+ // Delim is an optional delimiter output between each log field.
+ // Defaults to a single space.
+ Delim string `json:"delim"`
+
+ // MinLevelLen sets the minimum level name length. If the level name is less
+ // than the minimum it will be padded with spaces.
+ MinLevelLen int `json:"min_level_len"`
+
+ // MinMessageLen sets the minimum msg length. If the msg text is less
+ // than the minimum it will be padded with spaces.
+ MinMessageLen int `json:"min_msg_len"`
+
+ // TimestampFormat is an optional format for timestamps. If empty
+ // then DefTimestampFormat is used.
+ TimestampFormat string `json:"timestamp_format"`
+
+ // LineEnd sets the end of line character(s). Defaults to '\n'.
+ LineEnd string `json:"line_end"`
+
+ // EnableColor sets whether output should include color.
+ EnableColor bool `json:"enable_color"`
+}
+
+func (p *Plain) CheckValid() error {
+ if p.MinMessageLen < 0 || p.MinMessageLen > 1024 {
+ return fmt.Errorf("min_msg_len is invalid(%d)", p.MinMessageLen)
+ }
+ return nil
+}
+
+// IsStacktraceNeeded returns true if a stacktrace is needed so we can output the `Caller` field.
+func (p *Plain) IsStacktraceNeeded() bool {
+ return p.EnableCaller
+}
+
+// Format converts a log record to bytes.
+func (p *Plain) Format(rec *logr.LogRec, level logr.Level, buf *bytes.Buffer) (*bytes.Buffer, error) {
+ delim := p.Delim
+ if delim == "" {
+ delim = " "
+ }
+ if buf == nil {
+ buf = &bytes.Buffer{}
+ }
+
+ timestampFmt := p.TimestampFormat
+ if timestampFmt == "" {
+ timestampFmt = logr.DefTimestampFormat
+ }
+
+ color := logr.NoColor
+ if p.EnableColor {
+ color = level.Color
+ }
+
+ if !p.DisableLevel {
+ _ = logr.WriteWithColor(buf, level.Name, color)
+ count := len(level.Name)
+ if p.MinLevelLen > count {
+ _, _ = buf.WriteString(strings.Repeat(" ", p.MinLevelLen-count))
+ }
+ buf.WriteString(delim)
+ }
+
+ if !p.DisableTimestamp {
+ var arr [128]byte
+ tbuf := rec.Time().AppendFormat(arr[:0], timestampFmt)
+ buf.WriteByte('[')
+ buf.Write(tbuf)
+ buf.WriteByte(']')
+ buf.WriteString(delim)
+ }
+
+ if !p.DisableMsg {
+ count, _ := buf.WriteString(rec.Msg())
+ if p.MinMessageLen > count {
+ _, _ = buf.WriteString(strings.Repeat(" ", p.MinMessageLen-count))
+ }
+ _, _ = buf.WriteString(delim)
+ }
+
+ var fields []logr.Field
+
+ if p.EnableCaller {
+ fld := logr.Field{
+ Key: "caller",
+ Type: logr.StringType,
+ String: rec.Caller(),
+ }
+ fields = append(fields, fld)
+ }
+
+ if !p.DisableFields {
+ fields = append(fields, rec.Fields()...)
+ }
+
+ if len(fields) > 0 {
+ if err := logr.WriteFields(buf, fields, logr.Space, color); err != nil {
+ return nil, err
+ }
+ }
+
+ if level.Stacktrace && !p.DisableStacktrace {
+ frames := rec.StackFrames()
+ if len(frames) > 0 {
+ buf.WriteString("\n")
+ if err := logr.WriteStacktrace(buf, rec.StackFrames()); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ if p.LineEnd == "" {
+ buf.WriteString("\n")
+ } else {
+ buf.WriteString(p.LineEnd)
+ }
+
+ return buf, nil
+}
diff --git a/vendor/github.com/mattermost/logr/go.mod b/vendor/github.com/mattermost/logr/v2/go.mod
similarity index 55%
rename from vendor/github.com/mattermost/logr/go.mod
rename to vendor/github.com/mattermost/logr/v2/go.mod
index e8e8acfb2f..4cbe375e7d 100644
--- a/vendor/github.com/mattermost/logr/go.mod
+++ b/vendor/github.com/mattermost/logr/v2/go.mod
@@ -1,11 +1,11 @@
-module github.com/mattermost/logr
+module github.com/mattermost/logr/v2
go 1.12
require (
github.com/francoispqt/gojay v1.2.13
- github.com/stretchr/testify v1.2.2
- github.com/wiggin77/cfg v1.0.2
+ github.com/stretchr/testify v1.4.0
github.com/wiggin77/merror v1.0.2
+ github.com/wiggin77/srslog v1.0.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)
diff --git a/vendor/github.com/mattermost/logr/go.sum b/vendor/github.com/mattermost/logr/v2/go.sum
similarity index 97%
rename from vendor/github.com/mattermost/logr/go.sum
rename to vendor/github.com/mattermost/logr/v2/go.sum
index ea688513e9..ae50449220 100644
--- a/vendor/github.com/mattermost/logr/go.sum
+++ b/vendor/github.com/mattermost/logr/v2/go.sum
@@ -15,6 +15,7 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -93,15 +94,18 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
-github.com/wiggin77/cfg v1.0.2 h1:NBUX+iJRr+RTncTqTNvajHwzduqbhCQjEqxLHr6Fk7A=
-github.com/wiggin77/cfg v1.0.2/go.mod h1:b3gotba2e5bXTqTW48DwIFoLc+4lWKP7WPi/CdvZ4aE=
github.com/wiggin77/merror v1.0.2 h1:V0nH9eFp64ASyaXC+pB5WpvBoCg7NUwvaCSKdzlcHqw=
github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg=
+github.com/wiggin77/srslog v1.0.1 h1:gA2XjSMy3DrRdX9UqLuDtuVAAshb8bE1NhX1YK0Qe+8=
+github.com/wiggin77/srslog v1.0.1/go.mod h1:fehkyYDq1QfuYn60TDPu9YdY2bB85VUW2mvN1WynEls=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
diff --git a/vendor/github.com/mattermost/logr/v2/level.go b/vendor/github.com/mattermost/logr/v2/level.go
new file mode 100644
index 0000000000..643d68e34a
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/level.go
@@ -0,0 +1,34 @@
+package logr
+
+var AnsiColorPrefix = []byte("\u001b[")
+var AnsiColorSuffix = []byte("m")
+
+// Color for formatters that support color output.
+type Color uint8
+
+const (
+ NoColor Color = 0
+ Red Color = 31
+ Green Color = 32
+ Yellow Color = 33
+ Blue Color = 34
+ Magenta Color = 35
+ Cyan Color = 36
+ White Color = 37
+)
+
+// LevelID is the unique id of each level.
+type LevelID uint
+
+// Level provides a mechanism to enable/disable specific log lines.
+type Level struct {
+ ID LevelID `json:"id"`
+ Name string `json:"name"`
+ Stacktrace bool `json:"stacktrace,omitempty"`
+ Color Color `json:"color,omitempty"`
+}
+
+// String returns the name of this level.
+func (level Level) String() string {
+ return level.Name
+}
diff --git a/vendor/github.com/mattermost/logr/levelcache.go b/vendor/github.com/mattermost/logr/v2/levelcache.go
similarity index 100%
rename from vendor/github.com/mattermost/logr/levelcache.go
rename to vendor/github.com/mattermost/logr/v2/levelcache.go
diff --git a/vendor/github.com/mattermost/logr/v2/logger.go b/vendor/github.com/mattermost/logr/v2/logger.go
new file mode 100644
index 0000000000..6ce9c9f06f
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/logger.go
@@ -0,0 +1,99 @@
+package logr
+
+import "log"
+
+// Logger provides context for logging via fields.
+type Logger struct {
+ lgr *Logr
+ fields []Field
+}
+
+// Logr returns the `Logr` instance that created this `Logger`.
+func (logger Logger) Logr() *Logr {
+ return logger.lgr
+}
+
+// With creates a new `Logger` with any existing fields plus the new ones.
+func (logger Logger) With(fields ...Field) Logger {
+ l := Logger{lgr: logger.lgr}
+ size := len(logger.fields) + len(fields)
+ if size > 0 {
+ l.fields = make([]Field, 0, size)
+ l.fields = append(l.fields, logger.fields...)
+ l.fields = append(l.fields, fields...)
+ }
+ return l
+}
+
+// StdLogger creates a standard logger backed by this `Logr.Logger` instance.
+// All log records are emitted with the specified log level.
+func (logger Logger) StdLogger(level Level) *log.Logger {
+ return NewStdLogger(level, logger)
+}
+
+// IsLevelEnabled determines if the specified level is enabled for at least
+// one log target.
+func (logger Logger) IsLevelEnabled(level Level) bool {
+ status := logger.Logr().IsLevelEnabled(level)
+ return status.Enabled
+}
+
+// Sugar creates a new `Logger` with a less structured API. Any fields are preserved.
+func (logger Logger) Sugar(fields ...Field) Sugar {
+ return Sugar{
+ logger: logger.With(fields...),
+ }
+}
+
+// Log checks that the level matches one or more targets, and
+// if so, generates a log record that is added to the Logr queue.
+// Arguments are handled in the manner of fmt.Print.
+func (logger Logger) Log(lvl Level, msg string, fields ...Field) {
+ status := logger.lgr.IsLevelEnabled(lvl)
+ if status.Enabled {
+ rec := NewLogRec(lvl, logger, msg, fields, status.Stacktrace)
+ logger.lgr.enqueue(rec)
+ }
+}
+
+// LogM calls `Log` multiple times, one for each level provided.
+func (logger Logger) LogM(levels []Level, msg string, fields ...Field) {
+ for _, lvl := range levels {
+ logger.Log(lvl, msg, fields...)
+ }
+}
+
+// Trace is a convenience method equivalent to `Log(TraceLevel, msg, fields...)`.
+func (logger Logger) Trace(msg string, fields ...Field) {
+ logger.Log(Trace, msg, fields...)
+}
+
+// Debug is a convenience method equivalent to `Log(DebugLevel, msg, fields...)`.
+func (logger Logger) Debug(msg string, fields ...Field) {
+ logger.Log(Debug, msg, fields...)
+}
+
+// Info is a convenience method equivalent to `Log(InfoLevel, msg, fields...)`.
+func (logger Logger) Info(msg string, fields ...Field) {
+ logger.Log(Info, msg, fields...)
+}
+
+// Warn is a convenience method equivalent to `Log(WarnLevel, msg, fields...)`.
+func (logger Logger) Warn(msg string, fields ...Field) {
+ logger.Log(Warn, msg, fields...)
+}
+
+// Error is a convenience method equivalent to `Log(ErrorLevel, msg, fields...)`.
+func (logger Logger) Error(msg string, fields ...Field) {
+ logger.Log(Error, msg, fields...)
+}
+
+// Fatal is a convenience method equivalent to `Log(FatalLevel, msg, fields...)`
+func (logger Logger) Fatal(msg string, fields ...Field) {
+ logger.Log(Fatal, msg, fields...)
+}
+
+// Panic is a convenience method equivalent to `Log(PanicLevel, msg, fields...)`
+func (logger Logger) Panic(msg string, fields ...Field) {
+ logger.Log(Panic, msg, fields...)
+}
diff --git a/vendor/github.com/mattermost/logr/v2/logr.go b/vendor/github.com/mattermost/logr/v2/logr.go
new file mode 100644
index 0000000000..82b2a835f1
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/logr.go
@@ -0,0 +1,471 @@
+package logr
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/wiggin77/merror"
+)
+
+// Logr maintains a list of log targets and accepts incoming
+// log records. Use `New` to create instances.
+type Logr struct {
+ tmux sync.RWMutex // targetHosts mutex
+ targetHosts []*TargetHost
+
+ in chan *LogRec
+ quit chan struct{} // closed by Shutdown to exit read loop
+ done chan struct{} // closed when read loop exited
+ lvlCache levelCache
+ bufferPool sync.Pool
+ options *options
+
+ metricsMux sync.RWMutex
+ metrics *metrics
+
+ shutdown int32
+}
+
+// New creates a new Logr instance with one or more options specified.
+// Some options with invalid values can cause an error to be returned,
+// however `logr.New()` using just defaults never errors.
+func New(opts ...Option) (*Logr, error) {
+ options := &options{
+ maxQueueSize: DefaultMaxQueueSize,
+ enqueueTimeout: DefaultEnqueueTimeout,
+ shutdownTimeout: DefaultShutdownTimeout,
+ flushTimeout: DefaultFlushTimeout,
+ maxPooledBuffer: DefaultMaxPooledBuffer,
+ }
+
+ lgr := &Logr{options: options}
+
+ // apply the options
+ for _, opt := range opts {
+ if err := opt(lgr); err != nil {
+ return nil, err
+ }
+ }
+ pkgName := GetLogrPackageName()
+ if pkgName != "" {
+ opt := StackFilter(pkgName, pkgName+"/targets", pkgName+"/formatters")
+ _ = opt(lgr)
+ }
+
+ lgr.in = make(chan *LogRec, lgr.options.maxQueueSize)
+ lgr.quit = make(chan struct{})
+ lgr.done = make(chan struct{})
+
+ if lgr.options.useSyncMapLevelCache {
+ lgr.lvlCache = &syncMapLevelCache{}
+ } else {
+ lgr.lvlCache = &arrayLevelCache{}
+ }
+ lgr.lvlCache.setup()
+
+ lgr.bufferPool = sync.Pool{
+ New: func() interface{} {
+ return new(bytes.Buffer)
+ },
+ }
+
+ lgr.initMetrics(lgr.options.metricsCollector, lgr.options.metricsUpdateFreqMillis)
+
+ go lgr.start()
+
+ return lgr, nil
+}
+
+// AddTarget adds a target to the logger which will receive
+// log records for outputting.
+func (lgr *Logr) AddTarget(target Target, name string, filter Filter, formatter Formatter, maxQueueSize int) error {
+ if lgr.IsShutdown() {
+ return fmt.Errorf("AddTarget called after Logr shut down")
+ }
+
+ lgr.metricsMux.RLock()
+ metrics := lgr.metrics
+ lgr.metricsMux.RUnlock()
+
+ hostOpts := targetHostOptions{
+ name: name,
+ filter: filter,
+ formatter: formatter,
+ maxQueueSize: maxQueueSize,
+ metrics: metrics,
+ }
+
+ host, err := newTargetHost(target, hostOpts)
+ if err != nil {
+ return err
+ }
+
+ lgr.tmux.Lock()
+ defer lgr.tmux.Unlock()
+
+ lgr.targetHosts = append(lgr.targetHosts, host)
+
+ lgr.ResetLevelCache()
+
+ return nil
+}
+
+// NewLogger creates a Logger using defaults. A `Logger` is light-weight
+// enough to create on-demand, but typically one or more Loggers are
+// created and re-used.
+func (lgr *Logr) NewLogger() Logger {
+ logger := Logger{lgr: lgr}
+ return logger
+}
+
+var levelStatusDisabled = LevelStatus{}
+
+// IsLevelEnabled returns true if at least one target has the specified
+// level enabled. The result is cached so that subsequent checks are fast.
+func (lgr *Logr) IsLevelEnabled(lvl Level) LevelStatus {
+ // No levels enabled after shutdown
+ if atomic.LoadInt32(&lgr.shutdown) != 0 {
+ return levelStatusDisabled
+ }
+
+ // Check cache.
+ status, ok := lgr.lvlCache.get(lvl.ID)
+ if ok {
+ return status
+ }
+
+ status = LevelStatus{}
+
+ // Cache miss; check each target.
+ lgr.tmux.RLock()
+ defer lgr.tmux.RUnlock()
+ for _, host := range lgr.targetHosts {
+ enabled, level := host.IsLevelEnabled(lvl)
+ if enabled {
+ status.Enabled = true
+ if level.Stacktrace || host.formatter.IsStacktraceNeeded() {
+ status.Stacktrace = true
+ break // if both level and stacktrace enabled then no sense checking more targets
+ }
+ }
+ }
+
+ // Cache and return the result.
+ if err := lgr.lvlCache.put(lvl.ID, status); err != nil {
+ lgr.ReportError(err)
+ return LevelStatus{}
+ }
+ return status
+}
+
+// HasTargets returns true only if at least one target exists within the lgr.
+func (lgr *Logr) HasTargets() bool {
+ lgr.tmux.RLock()
+ defer lgr.tmux.RUnlock()
+ return len(lgr.targetHosts) > 0
+}
+
+// TargetInfo provides name and type for a Target.
+type TargetInfo struct {
+ Name string
+ Type string
+}
+
+// TargetInfos enumerates all the targets added to this lgr.
+// The resulting slice represents a snapshot at time of calling.
+func (lgr *Logr) TargetInfos() []TargetInfo {
+ infos := make([]TargetInfo, 0)
+
+ lgr.tmux.RLock()
+ defer lgr.tmux.RUnlock()
+
+ for _, host := range lgr.targetHosts {
+ inf := TargetInfo{
+ Name: host.String(),
+ Type: fmt.Sprintf("%T", host.target),
+ }
+ infos = append(infos, inf)
+ }
+ return infos
+}
+
+// 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 (lgr *Logr) RemoveTargets(cxt context.Context, f func(ti TargetInfo) bool) error {
+ errs := merror.New()
+ hosts := make([]*TargetHost, 0)
+
+ lgr.tmux.Lock()
+ defer lgr.tmux.Unlock()
+
+ for _, host := range lgr.targetHosts {
+ inf := TargetInfo{
+ Name: host.String(),
+ Type: fmt.Sprintf("%T", host.target),
+ }
+ if f(inf) {
+ if err := host.Shutdown(cxt); err != nil {
+ errs.Append(err)
+ }
+ } else {
+ hosts = append(hosts, host)
+ }
+ }
+
+ lgr.targetHosts = hosts
+ lgr.ResetLevelCache()
+
+ return errs.ErrorOrNil()
+}
+
+// ResetLevelCache resets the cached results of `IsLevelEnabled`. This is
+// called any time a Target is added or a target's level is changed.
+func (lgr *Logr) ResetLevelCache() {
+ lgr.lvlCache.clear()
+}
+
+// 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 Logr instead, or configure/reconfigure the Logr after calling this method.
+func (lgr *Logr) SetMetricsCollector(collector MetricsCollector, updateFreqMillis int64) {
+ lgr.initMetrics(collector, updateFreqMillis)
+}
+
+// enqueue adds a log record to the logr queue. If the queue is full then
+// this function either blocks or the log record is dropped, depending on
+// the result of calling `OnQueueFull`.
+func (lgr *Logr) enqueue(rec *LogRec) {
+ select {
+ case lgr.in <- rec:
+ default:
+ if lgr.options.onQueueFull != nil && lgr.options.onQueueFull(rec, cap(lgr.in)) {
+ return // drop the record
+ }
+ select {
+ case <-time.After(lgr.options.enqueueTimeout):
+ lgr.ReportError(fmt.Errorf("enqueue timed out for log rec [%v]", rec))
+ case lgr.in <- rec: // block until success or timeout
+ }
+ }
+}
+
+// Flush blocks while flushing the logr queue and all target queues, by
+// writing existing log records to valid targets.
+// Any attempts to add new log records will block until flush is complete.
+// `logr.FlushTimeout` determines how long flush can execute before
+// timing out. Use `IsTimeoutError` to determine if the returned error is
+// due to a timeout.
+func (lgr *Logr) Flush() error {
+ ctx, cancel := context.WithTimeout(context.Background(), lgr.options.flushTimeout)
+ defer cancel()
+ return lgr.FlushWithTimeout(ctx)
+}
+
+// Flush blocks while flushing the logr queue and all target queues, by
+// writing existing log records to valid targets.
+// Any attempts to add new log records will block until flush is complete.
+// Use `IsTimeoutError` to determine if the returned error is
+// due to a timeout.
+func (lgr *Logr) FlushWithTimeout(ctx context.Context) error {
+ if !lgr.HasTargets() {
+ return nil
+ }
+
+ if lgr.IsShutdown() {
+ return errors.New("Flush called on shut down Logr")
+ }
+
+ rec := newFlushLogRec(lgr.NewLogger())
+ lgr.enqueue(rec)
+
+ select {
+ case <-ctx.Done():
+ return newTimeoutError("logr queue flush timeout")
+ case <-rec.flush:
+ }
+ return nil
+}
+
+// IsShutdown returns true if this Logr instance has been shut down.
+// No further log records can be enqueued and no targets added after
+// shutdown.
+func (lgr *Logr) IsShutdown() bool {
+ return atomic.LoadInt32(&lgr.shutdown) != 0
+}
+
+// Shutdown cleanly stops the logging engine after making best efforts
+// to flush all targets. Call this function right before application
+// exit - logr cannot be restarted once shut down.
+// `logr.ShutdownTimeout` determines how long shutdown can execute before
+// timing out. Use `IsTimeoutError` to determine if the returned error is
+// due to a timeout.
+func (lgr *Logr) Shutdown() error {
+ ctx, cancel := context.WithTimeout(context.Background(), lgr.options.shutdownTimeout)
+ defer cancel()
+ return lgr.ShutdownWithTimeout(ctx)
+}
+
+// Shutdown cleanly stops the logging engine after making best efforts
+// to flush all targets. Call this function right before application
+// exit - logr cannot be restarted once shut down.
+// Use `IsTimeoutError` to determine if the returned error is due to a
+// timeout.
+func (lgr *Logr) ShutdownWithTimeout(ctx context.Context) error {
+ if err := lgr.FlushWithTimeout(ctx); err != nil {
+ return err
+ }
+
+ if atomic.SwapInt32(&lgr.shutdown, 1) != 0 {
+ return errors.New("Shutdown called again after shut down")
+ }
+
+ lgr.ResetLevelCache()
+ lgr.stopMetricsUpdater()
+
+ close(lgr.quit)
+
+ errs := merror.New()
+
+ // Wait for read loop to exit
+ select {
+ case <-ctx.Done():
+ errs.Append(newTimeoutError("logr queue shutdown timeout"))
+ case <-lgr.done:
+ }
+
+ // logr.in channel should now be drained to targets and no more log records
+ // can be added.
+ lgr.tmux.RLock()
+ defer lgr.tmux.RUnlock()
+ for _, host := range lgr.targetHosts {
+ err := host.Shutdown(ctx)
+ if err != nil {
+ errs.Append(err)
+ }
+ }
+ return errs.ErrorOrNil()
+}
+
+// ReportError is used to notify the host application of any internal logging errors.
+// If `OnLoggerError` is not nil, it is called with the error, otherwise the error is
+// output to `os.Stderr`.
+func (lgr *Logr) ReportError(err interface{}) {
+ lgr.incErrorCounter()
+
+ if lgr.options.onLoggerError == nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ lgr.options.onLoggerError(fmt.Errorf("%v", err))
+}
+
+// BorrowBuffer borrows a buffer from the pool. Release the buffer to reduce garbage collection.
+func (lgr *Logr) BorrowBuffer() *bytes.Buffer {
+ if lgr.options.disableBufferPool {
+ return &bytes.Buffer{}
+ }
+ return lgr.bufferPool.Get().(*bytes.Buffer)
+}
+
+// ReleaseBuffer returns a buffer to the pool to reduce garbage collection. The buffer is only
+// retained if less than MaxPooledBuffer.
+func (lgr *Logr) ReleaseBuffer(buf *bytes.Buffer) {
+ if !lgr.options.disableBufferPool && buf.Cap() < lgr.options.maxPooledBuffer {
+ buf.Reset()
+ lgr.bufferPool.Put(buf)
+ }
+}
+
+// start selects on incoming log records until shutdown record is received.
+// Incoming log records are fanned out to all log targets.
+func (lgr *Logr) start() {
+ defer func() {
+ if r := recover(); r != nil {
+ lgr.ReportError(r)
+ go lgr.start()
+ } else {
+ close(lgr.done)
+ }
+ }()
+
+ for {
+ var rec *LogRec
+ select {
+ case rec = <-lgr.in:
+ if rec.flush != nil {
+ lgr.flush(rec.flush)
+ } else {
+ rec.prep()
+ lgr.fanout(rec)
+ }
+ case <-lgr.quit:
+ return
+ }
+ }
+}
+
+// fanout pushes a LogRec to all targets.
+func (lgr *Logr) fanout(rec *LogRec) {
+ var host *TargetHost
+ defer func() {
+ if r := recover(); r != nil {
+ lgr.ReportError(fmt.Errorf("fanout failed for target %s, %v", host.String(), r))
+ }
+ }()
+
+ var logged bool
+
+ lgr.tmux.RLock()
+ defer lgr.tmux.RUnlock()
+ for _, host = range lgr.targetHosts {
+ if enabled, _ := host.IsLevelEnabled(rec.Level()); enabled {
+ host.Log(rec)
+ logged = true
+ }
+ }
+
+ if logged {
+ lgr.incLoggedCounter()
+ }
+}
+
+// flush drains the queue and notifies when done.
+func (lgr *Logr) flush(done chan<- struct{}) {
+ // first drain the logr queue.
+loop:
+ for {
+ var rec *LogRec
+ select {
+ case rec = <-lgr.in:
+ if rec.flush == nil {
+ rec.prep()
+ lgr.fanout(rec)
+ }
+ default:
+ break loop
+ }
+ }
+
+ logger := lgr.NewLogger()
+
+ // drain all the targets; block until finished.
+ lgr.tmux.RLock()
+ defer lgr.tmux.RUnlock()
+ for _, host := range lgr.targetHosts {
+ rec := newFlushLogRec(logger)
+ host.Log(rec)
+ <-rec.flush
+ }
+ done <- struct{}{}
+}
diff --git a/vendor/github.com/mattermost/logr/logrec.go b/vendor/github.com/mattermost/logr/v2/logrec.go
similarity index 60%
rename from vendor/github.com/mattermost/logr/logrec.go
rename to vendor/github.com/mattermost/logr/v2/logrec.go
index 9428aaec75..76d51b9e16 100644
--- a/vendor/github.com/mattermost/logr/logrec.go
+++ b/vendor/github.com/mattermost/logr/v2/logrec.go
@@ -2,24 +2,13 @@ package logr
import (
"fmt"
+ "path/filepath"
"runtime"
"strings"
"sync"
"time"
)
-var (
- logrPkg string
-)
-
-func init() {
- // Calc current package name
- pcs := make([]uintptr, 2)
- _ = runtime.Callers(0, pcs)
- tmp := runtime.FuncForPC(pcs[1]).Name()
- logrPkg = getPackageName(tmp)
-}
-
// LogRec collects raw, unformatted data to be logged.
// TODO: pool these? how to reliably know when targets are done with them? Copy for each target?
type LogRec struct {
@@ -29,9 +18,9 @@ type LogRec struct {
level Level
logger Logger
- template string
- newline bool
- args []interface{}
+ msg string
+ newline bool
+ fields []Field
stackPC []uintptr
stackCount int
@@ -40,13 +29,14 @@ type LogRec struct {
flush chan struct{}
// remaining fields calculated by `prep`
- msg string
- frames []runtime.Frame
+ frames []runtime.Frame
+ fieldsAll []Field
+ caller string
}
// NewLogRec creates a new LogRec with the current time and optional stack trace.
-func NewLogRec(lvl Level, logger Logger, template string, args []interface{}, incStacktrace bool) *LogRec {
- rec := &LogRec{time: time.Now(), logger: logger, level: lvl, template: template, args: args}
+func NewLogRec(lvl Level, logger Logger, msg string, fields []Field, incStacktrace bool) *LogRec {
+ rec := &LogRec{time: time.Now(), logger: logger, level: lvl, msg: msg, fields: fields}
if incStacktrace {
rec.stackPC = make([]uintptr, DefaultMaxStackFrames)
rec.stackCount = runtime.Callers(2, rec.stackPC)
@@ -60,44 +50,40 @@ func newFlushLogRec(logger Logger) *LogRec {
return &LogRec{logger: logger, flush: make(chan struct{})}
}
-// prep resolves all args and field values to strings, and
-// resolves stack trace to frames.
+// prep resolves stack trace to frames.
func (rec *LogRec) prep() {
rec.mux.Lock()
defer rec.mux.Unlock()
- // resolve args
- if rec.template == "" {
- if rec.newline {
- rec.msg = fmt.Sprintln(rec.args...)
- } else {
- rec.msg = fmt.Sprint(rec.args...)
- }
- } else {
- rec.msg = fmt.Sprintf(rec.template, rec.args...)
- }
+ // include log rec fields and logger fields added via "With"
+ rec.fieldsAll = make([]Field, 0, len(rec.fields)+len(rec.logger.fields))
+ rec.fieldsAll = append(rec.fieldsAll, rec.logger.fields...)
+ rec.fieldsAll = append(rec.fieldsAll, rec.fields...)
+
+ filter := rec.logger.lgr.options.stackFilter
// resolve stack trace
if rec.stackCount > 0 {
+ rec.frames = make([]runtime.Frame, 0, rec.stackCount)
frames := runtime.CallersFrames(rec.stackPC[:rec.stackCount])
for {
- f, more := frames.Next()
- rec.frames = append(rec.frames, f)
+ frame, more := frames.Next()
+
+ // remove all package entries that are in filter.
+ pkg := ResolvePackageName(frame.Function)
+ if _, ok := filter[pkg]; !ok && pkg != "" {
+ rec.frames = append(rec.frames, frame)
+ }
+
if !more {
break
}
}
+ }
- // remove leading logr package entries.
- var start int
- for i, frame := range rec.frames {
- pkg := getPackageName(frame.Function)
- if pkg != "" && pkg != logrPkg {
- start = i
- break
- }
- }
- rec.frames = rec.frames[start:]
+ // calc caller if stack trace provided
+ if len(rec.frames) > 0 {
+ rec.caller = calcCaller(rec.frames)
}
}
@@ -112,10 +98,9 @@ func (rec *LogRec) WithTime(time time.Time) *LogRec {
time: time,
level: rec.level,
logger: rec.logger,
- template: rec.template,
- newline: rec.newline,
- args: rec.args,
msg: rec.msg,
+ newline: rec.newline,
+ fields: rec.fields,
stackPC: rec.stackPC,
stackCount: rec.stackCount,
frames: rec.frames,
@@ -140,9 +125,9 @@ func (rec *LogRec) Level() Level {
}
// Fields returns this log record's Fields.
-func (rec *LogRec) Fields() Fields {
+func (rec *LogRec) Fields() []Field {
// no locking needed as this field is not mutated.
- return rec.logger.fields
+ return rec.fieldsAll
}
// Msg returns this log record's message text.
@@ -160,6 +145,15 @@ func (rec *LogRec) StackFrames() []runtime.Frame {
return rec.frames
}
+// Caller returns this log record's caller info, meaning the file and line
+// number where this log record was emitted. Returns empty string if no
+// stack trace was provided.
+func (rec *LogRec) Caller() string {
+ rec.mux.RLock()
+ defer rec.mux.RUnlock()
+ return rec.caller
+}
+
// String returns a string representation of this log record.
func (rec *LogRec) String() string {
if rec.flush != nil {
@@ -167,23 +161,22 @@ func (rec *LogRec) String() string {
}
f := &DefaultFormatter{}
- buf := rec.logger.logr.BorrowBuffer()
- defer rec.logger.logr.ReleaseBuffer(buf)
- buf, _ = f.Format(rec, true, buf)
+ buf := rec.logger.lgr.BorrowBuffer()
+ defer rec.logger.lgr.ReleaseBuffer(buf)
+ buf, _ = f.Format(rec, rec.Level(), buf)
return strings.TrimSpace(buf.String())
}
-// 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
+func calcCaller(frames []runtime.Frame) string {
+ for _, frame := range frames {
+ if frame.File == "" {
+ continue
}
+
+ dir, file := filepath.Split(frame.File)
+ base := filepath.Base(dir)
+
+ return fmt.Sprintf("%s/%s:%d", base, file, frame.Line)
}
- return f
+ return ""
}
diff --git a/vendor/github.com/mattermost/logr/metrics.go b/vendor/github.com/mattermost/logr/v2/metrics.go
similarity index 52%
rename from vendor/github.com/mattermost/logr/metrics.go
rename to vendor/github.com/mattermost/logr/v2/metrics.go
index 24fe22b6e5..f4f4d67fbb 100644
--- a/vendor/github.com/mattermost/logr/metrics.go
+++ b/vendor/github.com/mattermost/logr/v2/metrics.go
@@ -1,10 +1,6 @@
package logr
-import (
- "errors"
-
- "github.com/wiggin77/merror"
-)
+import "time"
const (
DefMetricsUpdateFreqMillis = 15000 // 15 seconds
@@ -52,66 +48,93 @@ type TargetWithMetrics interface {
EnableMetrics(collector MetricsCollector, updateFreqMillis int64) error
}
-func (logr *Logr) getMetricsCollector() MetricsCollector {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
- return logr.metrics
+type metrics struct {
+ collector MetricsCollector
+ updateFreqMillis int64
+ queueSizeGauge Gauge
+ loggedCounter Counter
+ errorCounter Counter
+ done chan struct{}
}
-// SetMetricsCollector enables metrics collection by supplying a MetricsCollector.
-// The MetricsCollector provides counters and gauges that are updated by log targets.
-func (logr *Logr) SetMetricsCollector(collector MetricsCollector) error {
+// initMetrics initializes metrics collection.
+func (lgr *Logr) initMetrics(collector MetricsCollector, updatefreq int64) {
+ lgr.stopMetricsUpdater()
+
if collector == nil {
- return errors.New("collector cannot be nil")
+ lgr.metricsMux.Lock()
+ lgr.metrics = nil
+ lgr.metricsMux.Unlock()
+ return
}
- logr.mux.Lock()
- logr.metrics = collector
- logr.queueSizeGauge, _ = collector.QueueSizeGauge("_logr")
- logr.loggedCounter, _ = collector.LoggedCounter("_logr")
- logr.errorCounter, _ = collector.ErrorCounter("_logr")
- logr.mux.Unlock()
+ metrics := &metrics{
+ collector: collector,
+ updateFreqMillis: updatefreq,
+ done: make(chan struct{}),
+ }
+ metrics.queueSizeGauge, _ = collector.QueueSizeGauge("_logr")
+ metrics.loggedCounter, _ = collector.LoggedCounter("_logr")
+ metrics.errorCounter, _ = collector.ErrorCounter("_logr")
- logr.metricsInitOnce.Do(func() {
- logr.metricsDone = make(chan struct{})
- go logr.startMetricsUpdater()
- })
+ lgr.metricsMux.Lock()
+ lgr.metrics = metrics
+ lgr.metricsMux.Unlock()
- merr := merror.New()
+ go lgr.startMetricsUpdater()
+}
- logr.tmux.RLock()
- defer logr.tmux.RUnlock()
- for _, target := range logr.targets {
- if tm, ok := target.(TargetWithMetrics); ok {
- if err := tm.EnableMetrics(collector, logr.MetricsUpdateFreqMillis); err != nil {
- merr.Append(err)
- }
+func (lgr *Logr) setQueueSizeGauge(val float64) {
+ lgr.metricsMux.RLock()
+ defer lgr.metricsMux.RUnlock()
+
+ if lgr.metrics != nil {
+ lgr.metrics.queueSizeGauge.Set(val)
+ }
+}
+
+func (lgr *Logr) incLoggedCounter() {
+ lgr.metricsMux.RLock()
+ defer lgr.metricsMux.RUnlock()
+
+ if lgr.metrics != nil {
+ lgr.metrics.loggedCounter.Inc()
+ }
+}
+
+func (lgr *Logr) incErrorCounter() {
+ lgr.metricsMux.RLock()
+ defer lgr.metricsMux.RUnlock()
+
+ if lgr.metrics != nil {
+ lgr.metrics.errorCounter.Inc()
+ }
+}
+
+// startMetricsUpdater updates the metrics for any polled values every `metricsUpdateFreqSecs` seconds until
+// logr is closed.
+func (lgr *Logr) startMetricsUpdater() {
+ for {
+ lgr.metricsMux.RLock()
+ metrics := lgr.metrics
+ c := metrics.done
+ lgr.metricsMux.RUnlock()
+
+ select {
+ case <-c:
+ return
+ case <-time.After(time.Duration(metrics.updateFreqMillis) * time.Millisecond):
+ lgr.setQueueSizeGauge(float64(len(lgr.in)))
}
-
- }
- return merr.ErrorOrNil()
-}
-
-func (logr *Logr) setQueueSizeGauge(val float64) {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
- if logr.queueSizeGauge != nil {
- logr.queueSizeGauge.Set(val)
}
}
-func (logr *Logr) incLoggedCounter() {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
- if logr.loggedCounter != nil {
- logr.loggedCounter.Inc()
- }
-}
+func (lgr *Logr) stopMetricsUpdater() {
+ lgr.metricsMux.Lock()
+ defer lgr.metricsMux.Unlock()
-func (logr *Logr) incErrorCounter() {
- logr.mux.RLock()
- defer logr.mux.RUnlock()
- if logr.errorCounter != nil {
- logr.errorCounter.Inc()
+ if lgr.metrics != nil && lgr.metrics.done != nil {
+ close(lgr.metrics.done)
+ lgr.metrics.done = nil
}
}
diff --git a/vendor/github.com/mattermost/logr/v2/options.go b/vendor/github.com/mattermost/logr/v2/options.go
new file mode 100644
index 0000000000..638f638ae6
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/options.go
@@ -0,0 +1,192 @@
+package logr
+
+import (
+ "errors"
+ "time"
+)
+
+type Option func(*Logr) error
+
+type options struct {
+ maxQueueSize int
+ onLoggerError func(error)
+ onQueueFull func(rec *LogRec, maxQueueSize int) bool
+ onTargetQueueFull func(target Target, rec *LogRec, maxQueueSize int) bool
+ onExit func(code int)
+ onPanic func(err interface{})
+ enqueueTimeout time.Duration
+ shutdownTimeout time.Duration
+ flushTimeout time.Duration
+ useSyncMapLevelCache bool
+ maxPooledBuffer int
+ disableBufferPool bool
+ metricsCollector MetricsCollector
+ metricsUpdateFreqMillis int64
+ stackFilter map[string]struct{}
+}
+
+// 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 func(l *Logr) error {
+ if size < 0 {
+ return errors.New("size cannot be less than zero")
+ }
+ l.options.maxQueueSize = size
+ return nil
+ }
+}
+
+// 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 func(l *Logr) error {
+ l.options.onLoggerError = f
+ return nil
+ }
+}
+
+// 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 func(l *Logr) error {
+ l.options.onQueueFull = f
+ return nil
+ }
+}
+
+// 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 func(l *Logr) error {
+ l.options.onTargetQueueFull = f
+ return nil
+ }
+}
+
+// OnExit, when not nil, is called when a FatalXXX style log API is called.
+// When nil, then the default behavior is to cleanly shut down this Logr and
+// call `os.Exit(code)`.
+func OnExit(f func(code int)) Option {
+ return func(l *Logr) error {
+ l.options.onExit = f
+ return nil
+ }
+}
+
+// OnPanic, when not nil, is called when a PanicXXX style log API is called.
+// When nil, then the default behavior is to cleanly shut down this Logr and
+// call `panic(err)`.
+func OnPanic(f func(err interface{})) Option {
+ return func(l *Logr) error {
+ l.options.onPanic = f
+ return nil
+ }
+}
+
+// EnqueueTimeout is the amount of time a log record can take to be queued.
+// This only applies to blocking enqueue which happen after `logr.OnQueueFull`
+// is called and returns false.
+func EnqueueTimeout(dur time.Duration) Option {
+ return func(l *Logr) error {
+ l.options.enqueueTimeout = dur
+ return nil
+ }
+}
+
+// ShutdownTimeout is the amount of time `logr.Shutdown` can execute before
+// timing out. An alternative is to use `logr.ShutdownWithContext` and supply
+// a timeout.
+func ShutdownTimeout(dur time.Duration) Option {
+ return func(l *Logr) error {
+ l.options.shutdownTimeout = dur
+ return nil
+ }
+}
+
+// FlushTimeout is the amount of time `logr.Flush` can execute before
+// timing out. An alternative is to use `logr.FlushWithContext` and supply
+// a timeout.
+func FlushTimeout(dur time.Duration) Option {
+ return func(l *Logr) error {
+ l.options.flushTimeout = dur
+ return nil
+ }
+}
+
+// UseSyncMapLevelCache can be set to true when high concurrency (e.g. >32 cores)
+// is expected. This may improve performance with large numbers of cores - benchmark
+// for your use case.
+func UseSyncMapLevelCache(use bool) Option {
+ return func(l *Logr) error {
+ l.options.useSyncMapLevelCache = use
+ return nil
+ }
+}
+
+// MaxPooledBufferSize determines the maximum size of a buffer that can be
+// pooled. To reduce allocations, the buffers needed during formatting (etc)
+// are pooled. A very large log item will grow a buffer that could stay in
+// memory indefinitely. This setting lets you control how big a pooled buffer
+// can be - anything larger will be garbage collected after use.
+// Defaults to 1MB.
+func MaxPooledBufferSize(size int) Option {
+ return func(l *Logr) error {
+ l.options.maxPooledBuffer = size
+ return nil
+ }
+}
+
+// DisableBufferPool when true disables the buffer pool. See MaxPooledBuffer.
+func DisableBufferPool(disable bool) Option {
+ return func(l *Logr) error {
+ l.options.disableBufferPool = disable
+ return nil
+ }
+}
+
+// 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 func(l *Logr) error {
+ if collector == nil {
+ return errors.New("collector cannot be nil")
+ }
+ if updateFreqMillis < 250 {
+ return errors.New("updateFreqMillis cannot be less than 250")
+ }
+ l.options.metricsCollector = collector
+ l.options.metricsUpdateFreqMillis = updateFreqMillis
+ return nil
+ }
+}
+
+// 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 func(l *Logr) error {
+ if l.options.stackFilter == nil {
+ l.options.stackFilter = make(map[string]struct{})
+ }
+
+ for _, p := range pkg {
+ if p != "" {
+ l.options.stackFilter[p] = struct{}{}
+ }
+ }
+ return nil
+ }
+}
diff --git a/vendor/github.com/mattermost/logr/v2/pkg.go b/vendor/github.com/mattermost/logr/v2/pkg.go
new file mode 100644
index 0000000000..873b2e953e
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/pkg.go
@@ -0,0 +1,57 @@
+package logr
+
+import (
+ "runtime"
+ "strings"
+ "sync"
+)
+
+const (
+ maximumStackDepth int = 30
+)
+
+var (
+ logrPkg string
+ pkgCalcOnce sync.Once
+)
+
+// GetPackageName returns the root package name of Logr.
+func GetLogrPackageName() string {
+ pkgCalcOnce.Do(func() {
+ logrPkg = GetPackageName("GetLogrPackageName")
+ })
+ return logrPkg
+}
+
+// GetPackageName returns the package name of the caller.
+// `callingFuncName` should be the name of the calling function and
+// should be unique enough not to collide with any runtime methods.
+func GetPackageName(callingFuncName string) string {
+ var pkgName string
+
+ pcs := make([]uintptr, maximumStackDepth)
+ _ = runtime.Callers(0, pcs)
+
+ for _, pc := range pcs {
+ funcName := runtime.FuncForPC(pc).Name()
+ if strings.Contains(funcName, callingFuncName) {
+ pkgName = ResolvePackageName(funcName)
+ break
+ }
+ }
+ return pkgName
+}
+
+// ResolvePackageName reduces a fully qualified function name to the package name
+func ResolvePackageName(f string) string {
+ for {
+ lastPeriod := strings.LastIndex(f, ".")
+ lastSlash := strings.LastIndex(f, "/")
+ if lastPeriod > lastSlash {
+ f = f[:lastPeriod]
+ } else {
+ break
+ }
+ }
+ return f
+}
diff --git a/vendor/github.com/mattermost/logr/v2/stdlogger.go b/vendor/github.com/mattermost/logr/v2/stdlogger.go
new file mode 100644
index 0000000000..50171b3df8
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/stdlogger.go
@@ -0,0 +1,56 @@
+package logr
+
+import (
+ "log"
+ "os"
+ "strings"
+)
+
+// NewStdLogger creates a standard logger backed by a Logr instance.
+// All log records are emitted with the specified log level.
+func NewStdLogger(level Level, logger Logger) *log.Logger {
+ adapter := newStdLogAdapter(logger, level)
+ return log.New(adapter, "", 0)
+}
+
+// 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 Logr 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.Stderr.
+func (lgr *Logr) RedirectStdLog(level Level, fields ...Field) func() {
+ flags := log.Flags()
+ prefix := log.Prefix()
+ log.SetFlags(0)
+ log.SetPrefix("")
+
+ logger := lgr.NewLogger().With(fields...)
+ adapter := newStdLogAdapter(logger, level)
+ log.SetOutput(adapter)
+
+ return func() {
+ log.SetFlags(flags)
+ log.SetPrefix(prefix)
+ log.SetOutput(os.Stderr)
+ }
+}
+
+type stdLogAdapter struct {
+ logger Logger
+ level Level
+}
+
+func newStdLogAdapter(logger Logger, level Level) *stdLogAdapter {
+ return &stdLogAdapter{
+ logger: logger,
+ level: level,
+ }
+}
+
+// Write implements io.Writer
+func (a *stdLogAdapter) Write(p []byte) (int, error) {
+ s := strings.TrimSpace(string(p))
+ a.logger.Log(a.level, s)
+ return len(p), nil
+}
diff --git a/vendor/github.com/mattermost/logr/v2/sugar.go b/vendor/github.com/mattermost/logr/v2/sugar.go
new file mode 100644
index 0000000000..f4f300eeac
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/sugar.go
@@ -0,0 +1,119 @@
+package logr
+
+import (
+ "fmt"
+)
+
+// Sugar provides a less structured API for logging.
+type Sugar struct {
+ logger Logger
+}
+
+func (s Sugar) sugarLog(lvl Level, msg string, args ...interface{}) {
+ if s.logger.IsLevelEnabled(lvl) {
+ fields := make([]Field, 0, len(args))
+ for _, arg := range args {
+ fields = append(fields, Any("", arg))
+ }
+ s.logger.Log(lvl, msg, fields...)
+ }
+}
+
+// Trace is a convenience method equivalent to `Log(TraceLevel, msg, args...)`.
+func (s Sugar) Trace(msg string, args ...interface{}) {
+ s.sugarLog(Trace, msg, args...)
+}
+
+// Debug is a convenience method equivalent to `Log(DebugLevel, msg, args...)`.
+func (s Sugar) Debug(msg string, args ...interface{}) {
+ s.sugarLog(Debug, msg, args...)
+}
+
+// Print ensures compatibility with std lib logger.
+func (s Sugar) Print(msg string, args ...interface{}) {
+ s.Info(msg, args...)
+}
+
+// Info is a convenience method equivalent to `Log(InfoLevel, msg, args...)`.
+func (s Sugar) Info(msg string, args ...interface{}) {
+ s.sugarLog(Info, msg, args...)
+}
+
+// Warn is a convenience method equivalent to `Log(WarnLevel, msg, args...)`.
+func (s Sugar) Warn(msg string, args ...interface{}) {
+ s.sugarLog(Warn, msg, args...)
+}
+
+// Error is a convenience method equivalent to `Log(ErrorLevel, msg, args...)`.
+func (s Sugar) Error(msg string, args ...interface{}) {
+ s.sugarLog(Error, msg, args...)
+}
+
+// Fatal is a convenience method equivalent to `Log(FatalLevel, msg, args...)`
+func (s Sugar) Fatal(msg string, args ...interface{}) {
+ s.sugarLog(Fatal, msg, args...)
+}
+
+// Panic is a convenience method equivalent to `Log(PanicLevel, msg, args...)`
+func (s Sugar) Panic(msg string, args ...interface{}) {
+ s.sugarLog(Panic, msg, args...)
+}
+
+//
+// Printf style
+//
+
+// Logf checks that the level matches one or more targets, and
+// if so, generates a log record that is added to the main
+// queue (channel). Arguments are handled in the manner of fmt.Printf.
+func (s Sugar) Logf(lvl Level, format string, args ...interface{}) {
+ if s.logger.IsLevelEnabled(lvl) {
+ var msg string
+ if format == "" {
+ msg = fmt.Sprint(args...)
+ } else {
+ msg = fmt.Sprintf(format, args...)
+ }
+ s.logger.Log(lvl, msg)
+ }
+}
+
+// Tracef is a convenience method equivalent to `Logf(TraceLevel, args...)`.
+func (s Sugar) Tracef(format string, args ...interface{}) {
+ s.Logf(Trace, format, args...)
+}
+
+// Debugf is a convenience method equivalent to `Logf(DebugLevel, args...)`.
+func (s Sugar) Debugf(format string, args ...interface{}) {
+ s.Logf(Debug, format, args...)
+}
+
+// Infof is a convenience method equivalent to `Logf(InfoLevel, args...)`.
+func (s Sugar) Infof(format string, args ...interface{}) {
+ s.Logf(Info, format, args...)
+}
+
+// Printf ensures compatibility with std lib logger.
+func (s Sugar) Printf(format string, args ...interface{}) {
+ s.Infof(format, args...)
+}
+
+// Warnf is a convenience method equivalent to `Logf(WarnLevel, args...)`.
+func (s Sugar) Warnf(format string, args ...interface{}) {
+ s.Logf(Warn, format, args...)
+}
+
+// Errorf is a convenience method equivalent to `Logf(ErrorLevel, args...)`.
+func (s Sugar) Errorf(format string, args ...interface{}) {
+ s.Logf(Error, format, args...)
+}
+
+// Fatalf is a convenience method equivalent to `Logf(FatalLevel, args...)`
+func (s Sugar) Fatalf(format string, args ...interface{}) {
+ s.Logf(Fatal, format, args...)
+}
+
+// Panicf is a convenience method equivalent to `Logf(PanicLevel, args...)`
+func (s Sugar) Panicf(format string, args ...interface{}) {
+ s.Logf(Panic, format, args...)
+}
diff --git a/vendor/github.com/mattermost/logr/v2/target.go b/vendor/github.com/mattermost/logr/v2/target.go
new file mode 100644
index 0000000000..fa0a9320cd
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/target.go
@@ -0,0 +1,304 @@
+package logr
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "sync/atomic"
+ "time"
+)
+
+// Target represents a destination for log records such as file,
+// database, TCP socket, etc.
+type Target interface {
+ // Init is called once to initialize the target.
+ Init() error
+
+ // Write outputs to this target's destination.
+ Write(p []byte, rec *LogRec) (int, error)
+
+ // Shutdown is called once to free/close any resources.
+ // Target queue is already drained when this is called.
+ Shutdown() error
+}
+
+type targetMetrics struct {
+ queueSizeGauge Gauge
+ loggedCounter Counter
+ errorCounter Counter
+ droppedCounter Counter
+ blockedCounter Counter
+}
+
+type targetHostOptions struct {
+ name string
+ filter Filter
+ formatter Formatter
+ maxQueueSize int
+ metrics *metrics
+}
+
+// TargetHost hosts and manages the lifecycle of a target.
+// Incoming log records are queued and formatted before
+// being passed to the target.
+type TargetHost struct {
+ target Target
+ name string
+
+ filter Filter
+ formatter Formatter
+
+ in chan *LogRec
+ quit chan struct{} // closed by Shutdown to exit read loop
+ done chan struct{} // closed when read loop exited
+ targetMetrics *targetMetrics
+
+ shutdown int32
+}
+
+func newTargetHost(target Target, options targetHostOptions) (*TargetHost, error) {
+ host := &TargetHost{
+ target: target,
+ name: options.name,
+ filter: options.filter,
+ formatter: options.formatter,
+ in: make(chan *LogRec, options.maxQueueSize),
+ quit: make(chan struct{}),
+ done: make(chan struct{}),
+ }
+
+ if host.name == "" {
+ host.name = fmt.Sprintf("%T", target)
+ }
+
+ if host.filter == nil {
+ host.filter = &StdFilter{Lvl: Fatal}
+ }
+ if host.formatter == nil {
+ host.formatter = &DefaultFormatter{}
+ }
+
+ err := host.initMetrics(options.metrics)
+ if err != nil {
+ return nil, err
+ }
+
+ err = target.Init()
+ if err != nil {
+ return nil, err
+ }
+
+ go host.start()
+
+ return host, nil
+}
+
+func (h *TargetHost) initMetrics(metrics *metrics) error {
+ if metrics == nil {
+ return nil
+ }
+
+ var err error
+ tmetrics := &targetMetrics{}
+
+ if tmetrics.queueSizeGauge, err = metrics.collector.QueueSizeGauge(h.name); err != nil {
+ return err
+ }
+ if tmetrics.loggedCounter, err = metrics.collector.LoggedCounter(h.name); err != nil {
+ return err
+ }
+ if tmetrics.errorCounter, err = metrics.collector.ErrorCounter(h.name); err != nil {
+ return err
+ }
+ if tmetrics.droppedCounter, err = metrics.collector.DroppedCounter(h.name); err != nil {
+ return err
+ }
+ if tmetrics.blockedCounter, err = metrics.collector.BlockedCounter(h.name); err != nil {
+ return err
+ }
+ h.targetMetrics = tmetrics
+
+ updateFreqMillis := metrics.updateFreqMillis
+ if updateFreqMillis == 0 {
+ updateFreqMillis = DefMetricsUpdateFreqMillis
+ }
+ if updateFreqMillis < 250 {
+ updateFreqMillis = 250 // don't peg the CPU
+ }
+
+ go h.startMetricsUpdater(updateFreqMillis)
+ return nil
+}
+
+// IsLevelEnabled returns true if this target should emit logs for the specified level.
+func (h *TargetHost) IsLevelEnabled(lvl Level) (enabled bool, level Level) {
+ level, enabled = h.filter.GetEnabledLevel(lvl)
+ return enabled, level
+}
+
+// Shutdown stops processing log records after making best
+// effort to flush queue.
+func (h *TargetHost) Shutdown(ctx context.Context) error {
+ if atomic.SwapInt32(&h.shutdown, 1) != 0 {
+ return errors.New("targetHost shutdown called more than once")
+ }
+
+ close(h.quit)
+
+ // No more records can be accepted; now wait for read loop to exit.
+ select {
+ case <-ctx.Done():
+ case <-h.done:
+ }
+
+ // b.in channel should now be drained.
+ return h.target.Shutdown()
+}
+
+// Log queues a log record to be output to this target's destination.
+func (h *TargetHost) Log(rec *LogRec) {
+ if atomic.LoadInt32(&h.shutdown) != 0 {
+ return
+ }
+
+ lgr := rec.Logger().Logr()
+ select {
+ case h.in <- rec:
+ default:
+ handler := lgr.options.onTargetQueueFull
+ if handler != nil && handler(h.target, rec, cap(h.in)) {
+ h.incDroppedCounter()
+ return // drop the record
+ }
+ h.incBlockedCounter()
+
+ select {
+ case <-time.After(lgr.options.enqueueTimeout):
+ lgr.ReportError(fmt.Errorf("target enqueue timeout for log rec [%v]", rec))
+ case h.in <- rec: // block until success or timeout
+ }
+ }
+}
+
+func (h *TargetHost) setQueueSizeGauge(val float64) {
+ if h.targetMetrics != nil {
+ h.targetMetrics.queueSizeGauge.Set(val)
+ }
+}
+
+func (h *TargetHost) incLoggedCounter() {
+ if h.targetMetrics != nil {
+ h.targetMetrics.loggedCounter.Inc()
+ }
+}
+
+func (h *TargetHost) incErrorCounter() {
+ if h.targetMetrics != nil {
+ h.targetMetrics.errorCounter.Inc()
+ }
+}
+
+func (h *TargetHost) incDroppedCounter() {
+ if h.targetMetrics != nil {
+ h.targetMetrics.droppedCounter.Inc()
+ }
+}
+
+func (h *TargetHost) incBlockedCounter() {
+ if h.targetMetrics != nil {
+ h.targetMetrics.blockedCounter.Inc()
+ }
+}
+
+// String returns a name for this target.
+func (h *TargetHost) String() string {
+ return h.name
+}
+
+// start accepts log records via In channel and writes to the
+// supplied target, until Done channel signaled.
+func (h *TargetHost) start() {
+ defer func() {
+ if r := recover(); r != nil {
+ fmt.Fprintln(os.Stderr, "TargetHost.start -- ", r)
+ go h.start()
+ } else {
+ close(h.done)
+ }
+ }()
+
+ for {
+ var rec *LogRec
+ select {
+ case rec = <-h.in:
+ if rec.flush != nil {
+ h.flush(rec.flush)
+ } else {
+ err := h.writeRec(rec)
+ if err != nil {
+ h.incErrorCounter()
+ rec.Logger().Logr().ReportError(err)
+ } else {
+ h.incLoggedCounter()
+ }
+ }
+ case <-h.quit:
+ return
+ }
+ }
+}
+
+func (h *TargetHost) writeRec(rec *LogRec) error {
+ level, enabled := h.filter.GetEnabledLevel(rec.Level())
+ if !enabled {
+ // how did we get here?
+ return fmt.Errorf("level %s not enabled for target %s", rec.Level().Name, h.name)
+ }
+
+ buf := rec.logger.lgr.BorrowBuffer()
+ defer rec.logger.lgr.ReleaseBuffer(buf)
+
+ buf, err := h.formatter.Format(rec, level, buf)
+ if err != nil {
+ return err
+ }
+
+ _, err = h.target.Write(buf.Bytes(), rec)
+ return err
+}
+
+// startMetricsUpdater updates the metrics for any polled values every `updateFreqMillis` seconds until
+// target is shut down.
+func (h *TargetHost) startMetricsUpdater(updateFreqMillis int64) {
+ for {
+ select {
+ case <-h.done:
+ return
+ case <-time.After(time.Duration(updateFreqMillis) * time.Millisecond):
+ h.setQueueSizeGauge(float64(len(h.in)))
+ }
+ }
+}
+
+// flush drains the queue and notifies when done.
+func (h *TargetHost) flush(done chan<- struct{}) {
+ for {
+ var rec *LogRec
+ var err error
+ select {
+ case rec = <-h.in:
+ // ignore any redundant flush records.
+ if rec.flush == nil {
+ err = h.writeRec(rec)
+ if err != nil {
+ h.incErrorCounter()
+ rec.Logger().Logr().ReportError(err)
+ }
+ }
+ default:
+ done <- struct{}{}
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/mattermost/logr/target/file.go b/vendor/github.com/mattermost/logr/v2/targets/file.go
similarity index 60%
rename from vendor/github.com/mattermost/logr/target/file.go
rename to vendor/github.com/mattermost/logr/v2/targets/file.go
index 0fd50768da..71133fac94 100644
--- a/vendor/github.com/mattermost/logr/target/file.go
+++ b/vendor/github.com/mattermost/logr/v2/targets/file.go
@@ -1,11 +1,10 @@
-package target
+package targets
import (
- "context"
+ "errors"
"io"
- "github.com/mattermost/logr"
- "github.com/wiggin77/merror"
+ "github.com/mattermost/logr/v2"
"gopkg.in/natefinch/lumberjack.v2"
)
@@ -13,38 +12,44 @@ type FileOptions struct {
// Filename is the file to write logs to. Backup log files will be retained
// in the same directory. It uses -lumberjack.log in
// os.TempDir() if empty.
- Filename string
+ Filename string `json:"filename"`
// MaxSize is the maximum size in megabytes of the log file before it gets
// rotated. It defaults to 100 megabytes.
- MaxSize int
+ MaxSize int `json:"max_size"`
// MaxAge is the maximum number of days to retain old log files based on the
// timestamp encoded in their filename. Note that a day is defined as 24
// hours and may not exactly correspond to calendar days due to daylight
// savings, leap seconds, etc. The default is not to remove old log files
// based on age.
- MaxAge int
+ MaxAge int `json:"max_age"`
// MaxBackups is the maximum number of old log files to retain. The default
// is to retain all old log files (though MaxAge may still cause them to get
// deleted.)
- MaxBackups int
+ MaxBackups int `json:"max_backups"`
// Compress determines if the rotated log files should be compressed
// using gzip. The default is not to perform compression.
- Compress bool
+ Compress bool `json:"compress"`
+}
+
+func (fo FileOptions) CheckValid() error {
+ if fo.Filename == "" {
+ return errors.New("filename cannot be empty")
+ }
+ return nil
}
// File outputs log records to a file which can be log rotated based on size or age.
// Uses `https://github.com/natefinch/lumberjack` for rotation.
type File struct {
- logr.Basic
out io.WriteCloser
}
// NewFileTarget creates a target capable of outputting log records to a rotated file.
-func NewFileTarget(filter logr.Filter, formatter logr.Formatter, opts FileOptions, maxQueue int) *File {
+func NewFileTarget(opts FileOptions) *File {
lumber := &lumberjack.Logger{
Filename: opts.Filename,
MaxSize: opts.MaxSize,
@@ -53,35 +58,21 @@ func NewFileTarget(filter logr.Filter, formatter logr.Formatter, opts FileOption
Compress: opts.Compress,
}
f := &File{out: lumber}
- f.Basic.Start(f, f, filter, formatter, maxQueue)
return f
}
-// Write converts the log record to bytes, via the Formatter,
-// and outputs to a file.
-func (f *File) Write(rec *logr.LogRec) error {
- _, stacktrace := f.IsLevelEnabled(rec.Level())
-
- buf := rec.Logger().Logr().BorrowBuffer()
- defer rec.Logger().Logr().ReleaseBuffer(buf)
-
- buf, err := f.Formatter().Format(rec, stacktrace, buf)
- if err != nil {
- return err
- }
- _, err = f.out.Write(buf.Bytes())
- return err
+// Init is called once to initialize the target.
+func (f *File) Init() error {
+ return nil
}
-// Shutdown flushes any remaining log records and closes the file.
-func (f *File) Shutdown(ctx context.Context) error {
- errs := merror.New()
-
- err := f.Basic.Shutdown(ctx)
- errs.Append(err)
-
- err = f.out.Close()
- errs.Append(err)
-
- return errs.ErrorOrNil()
+// Write outputs bytes to this file target.
+func (f *File) Write(p []byte, rec *logr.LogRec) (int, error) {
+ return f.out.Write(p)
+}
+
+// Shutdown is called once to free/close any resources.
+// Target queue is already drained when this is called.
+func (f *File) Shutdown() error {
+ return f.out.Close()
}
diff --git a/vendor/github.com/mattermost/logr/v2/targets/syslog.go b/vendor/github.com/mattermost/logr/v2/targets/syslog.go
new file mode 100644
index 0000000000..fc3fcc5fee
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/targets/syslog.go
@@ -0,0 +1,112 @@
+// +build !windows,!nacl,!plan9
+
+package targets
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+
+ "github.com/mattermost/logr/v2"
+ syslog "github.com/wiggin77/srslog"
+)
+
+// Syslog outputs log records to local or remote syslog.
+type Syslog struct {
+ params *SyslogOptions
+ writer *syslog.Writer
+}
+
+// SyslogOptions provides parameters for dialing a syslog daemon.
+type SyslogOptions struct {
+ IP string `json:"ip,omitempty"` // deprecated
+ Host string `json:"host"`
+ Port int `json:"port"`
+ TLS bool `json:"tls"`
+ Cert string `json:"cert"`
+ Insecure bool `json:"insecure"`
+ Tag string `json:"tag"`
+}
+
+func (so SyslogOptions) CheckValid() error {
+ if so.Host == "" && so.IP == "" {
+ return errors.New("missing host")
+ }
+ if so.Port == 0 {
+ return errors.New("missing port")
+ }
+ return nil
+}
+
+// NewSyslogTarget creates a target capable of outputting log records to remote or local syslog, with or without TLS.
+func NewSyslogTarget(params *SyslogOptions) (*Syslog, error) {
+ if params == nil {
+ return nil, errors.New("params cannot be nil")
+ }
+
+ s := &Syslog{
+ params: params,
+ }
+ return s, nil
+}
+
+// Init is called once to initialize the target.
+func (s *Syslog) Init() error {
+ network := "tcp"
+ var config *tls.Config
+
+ if s.params.TLS {
+ network = "tcp+tls"
+ config = &tls.Config{InsecureSkipVerify: s.params.Insecure}
+ if s.params.Cert != "" {
+ pool, err := GetCertPool(s.params.Cert)
+ if err != nil {
+ return err
+ }
+ config.RootCAs = pool
+ }
+ }
+ raddr := fmt.Sprintf("%s:%d", s.params.IP, s.params.Port)
+ if raddr == ":0" {
+ // If no IP:port provided then connect to local syslog.
+ raddr = ""
+ network = ""
+ }
+
+ var err error
+ s.writer, err = syslog.DialWithTLSConfig(network, raddr, syslog.LOG_INFO, s.params.Tag, config)
+ return err
+}
+
+// Write outputs bytes to this file target.
+func (s *Syslog) Write(p []byte, rec *logr.LogRec) (int, error) {
+ txt := string(p)
+ n := len(txt)
+ var err error
+
+ switch rec.Level() {
+ case logr.Panic, logr.Fatal:
+ err = s.writer.Crit(txt)
+ case logr.Error:
+ err = s.writer.Err(txt)
+ case logr.Warn:
+ err = s.writer.Warning(txt)
+ case logr.Debug, logr.Trace:
+ err = s.writer.Debug(txt)
+ default:
+ // logr.Info plus all custom levels.
+ err = s.writer.Info(txt)
+ }
+
+ if err != nil {
+ n = 0
+ // syslog writer will try to reconnect.
+ }
+ return n, err
+}
+
+// Shutdown is called once to free/close any resources.
+// Target queue is already drained when this is called.
+func (s *Syslog) Shutdown() error {
+ return s.writer.Close()
+}
diff --git a/vendor/github.com/mattermost/logr/v2/targets/syslog_unsupported.go b/vendor/github.com/mattermost/logr/v2/targets/syslog_unsupported.go
new file mode 100644
index 0000000000..e4086e9669
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/targets/syslog_unsupported.go
@@ -0,0 +1,56 @@
+// +build windows nacl plan9
+
+package targets
+
+import (
+ "errors"
+
+ "github.com/mattermost/logr/v2"
+ syslog "github.com/wiggin77/srslog"
+)
+
+const (
+ unsupported = "Syslog target is not supported on this platform."
+)
+
+// Syslog outputs log records to local or remote syslog.
+type Syslog struct {
+ params *SyslogOptions
+ writer *syslog.Writer
+}
+
+// SyslogOptions provides parameters for dialing a syslog daemon.
+type SyslogOptions struct {
+ IP string `json:"ip,omitempty"` // deprecated
+ Host string `json:"host"`
+ Port int `json:"port"`
+ TLS bool `json:"tls"`
+ Cert string `json:"cert"`
+ Insecure bool `json:"insecure"`
+ Tag string `json:"tag"`
+}
+
+func (so SyslogOptions) CheckValid() error {
+ return errors.New(unsupported)
+}
+
+// NewSyslogTarget creates a target capable of outputting log records to remote or local syslog, with or without TLS.
+func NewSyslogTarget(params *SyslogOptions) (*Syslog, error) {
+ return nil, errors.New(unsupported)
+}
+
+// Init is called once to initialize the target.
+func (s *Syslog) Init() error {
+ return errors.New(unsupported)
+}
+
+// Write outputs bytes to this file target.
+func (s *Syslog) Write(p []byte, rec *logr.LogRec) (int, error) {
+ return 0, errors.New(unsupported)
+}
+
+// Shutdown is called once to free/close any resources.
+// Target queue is already drained when this is called.
+func (s *Syslog) Shutdown() error {
+ return errors.New(unsupported)
+}
diff --git a/shared/mlog/tcp.go b/vendor/github.com/mattermost/logr/v2/targets/tcp.go
similarity index 54%
rename from shared/mlog/tcp.go
rename to vendor/github.com/mattermost/logr/v2/targets/tcp.go
index 7a6e6d1327..ce73e03406 100644
--- a/shared/mlog/tcp.go
+++ b/vendor/github.com/mattermost/logr/v2/targets/tcp.go
@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-package mlog
+package targets
import (
"context"
@@ -9,12 +9,10 @@ import (
"errors"
"fmt"
"net"
- _ "net/http/pprof"
"sync"
"time"
- "github.com/hashicorp/go-multierror"
- "github.com/mattermost/logr"
+ "github.com/mattermost/logr/v2"
)
const (
@@ -24,12 +22,10 @@ const (
MaxRetryBackoffMillis int64 = 30 * 1000 // 30 seconds
)
-// TCP outputs log records to raw socket server.
-type TCP struct {
- logr.Basic
-
- params *TCPParams
- addy string
+// Tcp outputs log records to raw socket server.
+type Tcp struct {
+ options *TcpOptions
+ addy string
mutex sync.Mutex
conn net.Conn
@@ -37,39 +33,49 @@ type TCP struct {
shutdown chan struct{}
}
-// TCPParams provides parameters for dialing a socket server.
-type TCPParams struct {
- IP string `json:"IP"`
- Port int `json:"Port"`
- TLS bool `json:"TLS"`
- Cert string `json:"Cert"`
- Insecure bool `json:"Insecure"`
+// TcpOptions provides parameters for dialing a socket server.
+type TcpOptions struct {
+ IP string `json:"ip,omitempty"` // deprecated
+ Host string `json:"host"`
+ Port int `json:"port"`
+ TLS bool `json:"tls"`
+ Cert string `json:"cert"`
+ Insecure bool `json:"insecure"`
}
-// NewTPCTarget creates a target capable of outputting log records to a raw socket, with or without TLS.
-func NewTCPTarget(filter logr.Filter, formatter logr.Formatter, params *TCPParams, maxQueue int) (*TCP, error) {
- tcp := &TCP{
- params: params,
- addy: fmt.Sprintf("%s:%d", params.IP, params.Port),
+func (to TcpOptions) CheckValid() error {
+ if to.Host == "" && to.IP == "" {
+ return errors.New("missing host")
+ }
+ if to.Port == 0 {
+ return errors.New("missing port")
+ }
+ return nil
+}
+
+// NewTcpTarget creates a target capable of outputting log records to a raw socket, with or without TLS.
+func NewTcpTarget(options *TcpOptions) *Tcp {
+ tcp := &Tcp{
+ options: options,
+ addy: fmt.Sprintf("%s:%d", options.IP, options.Port),
monitor: make(chan struct{}),
shutdown: make(chan struct{}),
}
- tcp.Basic.Start(tcp, tcp, filter, formatter, maxQueue)
+ return tcp
+}
- return tcp, nil
+// Init is called once to initialize the target.
+func (tcp *Tcp) Init() error {
+ return nil
}
// getConn provides a net.Conn. If a connection already exists, it is returned immediately,
// otherwise this method blocks until a new connection is created, timeout or shutdown.
-func (tcp *TCP) getConn() (net.Conn, error) {
+func (tcp *Tcp) getConn(reporter func(err interface{})) (net.Conn, error) {
tcp.mutex.Lock()
defer tcp.mutex.Unlock()
- Log(LvlTCPLogTarget, "getConn enter", String("addy", tcp.addy))
- defer Log(LvlTCPLogTarget, "getConn exit", String("addy", tcp.addy))
-
if tcp.conn != nil {
- Log(LvlTCPLogTarget, "reusing existing conn", String("addy", tcp.addy)) // use "With" once Zap is removed
return tcp.conn, nil
}
@@ -83,13 +89,14 @@ func (tcp *TCP) getConn() (net.Conn, error) {
defer cancel()
go func(ctx context.Context, ch chan result) {
- Log(LvlTCPLogTarget, "dailing", String("addy", tcp.addy))
conn, err := tcp.dial(ctx)
- if err == nil {
- tcp.conn = conn
- tcp.monitor = make(chan struct{})
- go monitor(tcp.conn, tcp.monitor, Log)
+ if err != nil {
+ reporter(fmt.Errorf("log target %s connection error: %w", tcp.String(), err))
+ return
}
+ tcp.conn = conn
+ tcp.monitor = make(chan struct{})
+ go monitor(tcp.conn, tcp.monitor)
ch <- result{conn: conn, err: err}
}(ctx, connChan)
@@ -103,26 +110,24 @@ func (tcp *TCP) getConn() (net.Conn, error) {
// dial connects to a TCP socket, and optionally performs a TLS handshake.
// A non-nil context must be provided which can cancel the dial.
-func (tcp *TCP) dial(ctx context.Context) (net.Conn, error) {
+func (tcp *Tcp) dial(ctx context.Context) (net.Conn, error) {
var dialer net.Dialer
dialer.Timeout = time.Second * DialTimeoutSecs
- conn, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%d", tcp.params.IP, tcp.params.Port))
+ conn, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%d", tcp.options.IP, tcp.options.Port))
if err != nil {
return nil, err
}
- if !tcp.params.TLS {
+ if !tcp.options.TLS {
return conn, nil
}
- Log(LvlTCPLogTarget, "TLS handshake", String("addy", tcp.addy))
-
tlsconfig := &tls.Config{
- ServerName: tcp.params.IP,
- InsecureSkipVerify: tcp.params.Insecure,
+ ServerName: tcp.options.IP,
+ InsecureSkipVerify: tcp.options.Insecure,
}
- if tcp.params.Cert != "" {
- pool, err := getCertPool(tcp.params.Cert)
+ if tcp.options.Cert != "" {
+ pool, err := GetCertPool(tcp.options.Cert)
if err != nil {
return nil, err
}
@@ -136,13 +141,12 @@ func (tcp *TCP) dial(ctx context.Context) (net.Conn, error) {
return tlsConn, nil
}
-func (tcp *TCP) close() error {
+func (tcp *Tcp) close() error {
tcp.mutex.Lock()
defer tcp.mutex.Unlock()
var err error
if tcp.conn != nil {
- Log(LvlTCPLogTarget, "closing connection", String("addy", tcp.addy))
close(tcp.monitor)
err = tcp.conn.Close()
tcp.conn = nil
@@ -151,69 +155,49 @@ func (tcp *TCP) close() error {
}
// Shutdown stops processing log records after making best effort to flush queue.
-func (tcp *TCP) Shutdown(ctx context.Context) error {
- errs := &multierror.Error{}
-
- Log(LvlTCPLogTarget, "shutting down", String("addy", tcp.addy))
-
- if err := tcp.Basic.Shutdown(ctx); err != nil {
- errs = multierror.Append(errs, err)
- }
-
- if err := tcp.close(); err != nil {
- errs = multierror.Append(errs, err)
- }
-
+func (tcp *Tcp) Shutdown() error {
+ err := tcp.close()
close(tcp.shutdown)
- return errs.ErrorOrNil()
+ return err
}
// Write converts the log record to bytes, via the Formatter, and outputs to the socket.
// Called by dedicated target goroutine and will block until success or shutdown.
-func (tcp *TCP) Write(rec *logr.LogRec) error {
- _, stacktrace := tcp.IsLevelEnabled(rec.Level())
-
- buf := rec.Logger().Logr().BorrowBuffer()
- defer rec.Logger().Logr().ReleaseBuffer(buf)
-
- buf, err := tcp.Formatter().Format(rec, stacktrace, buf)
- if err != nil {
- return err
- }
-
+func (tcp *Tcp) Write(p []byte, rec *logr.LogRec) (int, error) {
try := 1
backoff := RetryBackoffMillis
for {
select {
case <-tcp.shutdown:
- return err
+ return 0, nil
default:
}
- conn, err := tcp.getConn()
+ reporter := rec.Logger().Logr().ReportError
+
+ conn, err := tcp.getConn(reporter)
if err != nil {
- Log(LvlTCPLogTarget, "failed getting connection", String("addy", tcp.addy), Err(err))
- reporter := rec.Logger().Logr().ReportError
reporter(fmt.Errorf("log target %s connection error: %w", tcp.String(), err))
backoff = tcp.sleep(backoff)
continue
}
- conn.SetWriteDeadline(time.Now().Add(time.Second * WriteTimeoutSecs))
- _, err = buf.WriteTo(conn)
- if err == nil {
- return nil
+ err = conn.SetWriteDeadline(time.Now().Add(time.Second * WriteTimeoutSecs))
+ if err != nil {
+ reporter(fmt.Errorf("log target %s set write deadline error: %w", tcp.String(), err))
+ }
+
+ count, err := conn.Write(p)
+ if err == nil {
+ return count, nil
}
- Log(LvlTCPLogTarget, "write error", String("addy", tcp.addy), Err(err))
- reporter := rec.Logger().Logr().ReportError
reporter(fmt.Errorf("log target %s write error: %w", tcp.String(), err))
_ = tcp.close()
backoff = tcp.sleep(backoff)
try++
- Log(LvlTCPLogTarget, "retrying write", String("addy", tcp.addy), Int("try", try))
}
}
@@ -221,14 +205,9 @@ func (tcp *TCP) Write(rec *logr.LogRec) error {
// This is needed because TCP target uses a write only socket and Linux systems
// take a long time to detect a loss of connectivity on a socket when only writing;
// the writes simply fail without an error returned.
-func monitor(conn net.Conn, done <-chan struct{}, logFunc LogFuncCustom) {
- addy := conn.RemoteAddr().String()
- defer logFunc(LvlTCPLogTarget, "monitor exiting", String("addy", addy))
-
+func monitor(conn net.Conn, done <-chan struct{}) {
buf := make([]byte, 1)
for {
- logFunc(LvlTCPLogTarget, "monitor loop", String("addy", addy))
-
select {
case <-done:
return
@@ -248,18 +227,17 @@ func monitor(conn net.Conn, done <-chan struct{}, logFunc LogFuncCustom) {
}
// Any other error closes the connection, forcing a reconnect.
- logFunc(LvlTCPLogTarget, "monitor closing connection", Err(err))
conn.Close()
return
}
}
// String returns a string representation of this target.
-func (tcp *TCP) String() string {
- return fmt.Sprintf("TcpTarget[%s:%d]", tcp.params.IP, tcp.params.Port)
+func (tcp *Tcp) String() string {
+ return fmt.Sprintf("TcpTarget[%s:%d]", tcp.options.IP, tcp.options.Port)
}
-func (tcp *TCP) sleep(backoff int64) int64 {
+func (tcp *Tcp) sleep(backoff int64) int64 {
select {
case <-tcp.shutdown:
case <-time.After(time.Millisecond * time.Duration(backoff)):
diff --git a/shared/mlog/test-tls-client-cert.pem b/vendor/github.com/mattermost/logr/v2/targets/test-tls-client-cert.pem
similarity index 100%
rename from shared/mlog/test-tls-client-cert.pem
rename to vendor/github.com/mattermost/logr/v2/targets/test-tls-client-cert.pem
diff --git a/vendor/github.com/mattermost/logr/v2/targets/utils.go b/vendor/github.com/mattermost/logr/v2/targets/utils.go
new file mode 100644
index 0000000000..6e605af282
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/targets/utils.go
@@ -0,0 +1,33 @@
+package targets
+
+import (
+ "crypto/x509"
+ "encoding/base64"
+ "errors"
+ "io/ioutil"
+)
+
+// GetCertPool returns a x509.CertPool containing the cert(s)
+// from `cert`, which can be a path to a .pem or .crt file,
+// or a base64 encoded cert.
+func GetCertPool(cert string) (*x509.CertPool, error) {
+ if cert == "" {
+ return nil, errors.New("no cert provided")
+ }
+
+ // first treat as a file and try to read.
+ serverCert, err := ioutil.ReadFile(cert)
+ if err != nil {
+ // maybe it's a base64 encoded cert
+ serverCert, err = base64.StdEncoding.DecodeString(cert)
+ if err != nil {
+ return nil, errors.New("cert cannot be read")
+ }
+ }
+
+ pool := x509.NewCertPool()
+ if ok := pool.AppendCertsFromPEM(serverCert); ok {
+ return pool, nil
+ }
+ return nil, errors.New("cannot parse cert")
+}
diff --git a/vendor/github.com/mattermost/logr/v2/targets/writer.go b/vendor/github.com/mattermost/logr/v2/targets/writer.go
new file mode 100644
index 0000000000..d9f64d7688
--- /dev/null
+++ b/vendor/github.com/mattermost/logr/v2/targets/writer.go
@@ -0,0 +1,38 @@
+package targets
+
+import (
+ "io"
+ "io/ioutil"
+
+ "github.com/mattermost/logr/v2"
+)
+
+// Writer outputs log records to any `io.Writer`.
+type Writer struct {
+ out io.Writer
+}
+
+// NewWriterTarget creates a target capable of outputting log records to an io.Writer.
+func NewWriterTarget(out io.Writer) *Writer {
+ if out == nil {
+ out = ioutil.Discard
+ }
+ w := &Writer{out: out}
+ return w
+}
+
+// Init is called once to initialize the target.
+func (w *Writer) Init() error {
+ return nil
+}
+
+// Write outputs bytes to this file target.
+func (w *Writer) Write(p []byte, rec *logr.LogRec) (int, error) {
+ return w.out.Write(p)
+}
+
+// Shutdown is called once to free/close any resources.
+// Target queue is already drained when this is called.
+func (w *Writer) Shutdown() error {
+ return nil
+}
diff --git a/vendor/github.com/mattermost/logr/timeout.go b/vendor/github.com/mattermost/logr/v2/timeout.go
similarity index 100%
rename from vendor/github.com/mattermost/logr/timeout.go
rename to vendor/github.com/mattermost/logr/v2/timeout.go
diff --git a/vendor/github.com/wiggin77/cfg/.gitignore b/vendor/github.com/wiggin77/cfg/.gitignore
deleted file mode 100644
index f1c181ec9c..0000000000
--- a/vendor/github.com/wiggin77/cfg/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, build with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
diff --git a/vendor/github.com/wiggin77/cfg/.travis.yml b/vendor/github.com/wiggin77/cfg/.travis.yml
deleted file mode 100644
index 9899b387da..0000000000
--- a/vendor/github.com/wiggin77/cfg/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: go
-sudo: false
-before_script:
- - go vet ./...
-
\ No newline at end of file
diff --git a/vendor/github.com/wiggin77/cfg/LICENSE b/vendor/github.com/wiggin77/cfg/LICENSE
deleted file mode 100644
index 2b0bf7efa1..0000000000
--- a/vendor/github.com/wiggin77/cfg/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018 wiggin77
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/wiggin77/cfg/README.md b/vendor/github.com/wiggin77/cfg/README.md
deleted file mode 100644
index 583a82cb19..0000000000
--- a/vendor/github.com/wiggin77/cfg/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# cfg
-
-[](https://godoc.org/github.com/wiggin77/cfg)
-[](https://travis-ci.org/wiggin77/cfg)
-
-Go package for app configuration. Supports chained configuration sources for multiple levels of defaults.
-Includes APIs for loading Linux style configuration files (name/value pairs) or INI files, map based properties,
-or easily create new configuration sources (e.g. load from database).
-
-Supports monitoring configuration sources for changes, hot loading properties, and notifying listeners of changes.
-
-## Usage
-
-```Go
-config := &cfg.Config{}
-defer config.Shutdown() // stops monitoring
-
-// load file via filespec string, os.File
-src, err := Config.NewSrcFileFromFilespec("./myfile.conf")
-if err != nil {
- return err
-}
-// add src to top of chain, meaning first searched
-cfg.PrependSource(src)
-
-// fetch prop 'retries', default to 3 if not found
-val := config.Int("retries", 3)
-```
-
-See [example](./example_test.go) for more complete example, including listening for configuration changes.
-
-Config API parses the following data types:
-
-| type | method | example property values |
-| ------- | ------ | -------- |
-| string | Config.String | test, "" |
-| int | Config.Int | -1, 77, 0 |
-| int64 | Config.Int64 | -9223372036854775, 372036854775808 |
-| float64 | Config.Float64 | -77.3456, 95642331.1 |
-| bool | Config.Bool | T,t,true,True,1,0,False,false,f,F |
-| time.Duration | Config.Duration | "10ms", "2 hours", "5 min" * |
-
-\* Units of measure supported: ms, sec, min, hour, day, week, year.
diff --git a/vendor/github.com/wiggin77/cfg/config.go b/vendor/github.com/wiggin77/cfg/config.go
deleted file mode 100644
index 0e958102e7..0000000000
--- a/vendor/github.com/wiggin77/cfg/config.go
+++ /dev/null
@@ -1,366 +0,0 @@
-package cfg
-
-import (
- "errors"
- "fmt"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/wiggin77/cfg/timeconv"
-)
-
-// ErrNotFound returned when an operation is attempted on a
-// resource that doesn't exist, such as fetching a non-existing
-// property name.
-var ErrNotFound = errors.New("not found")
-
-type sourceEntry struct {
- src Source
- props map[string]string
-}
-
-// Config provides methods for retrieving property values from one or more
-// configuration sources.
-type Config struct {
- mutexSrc sync.RWMutex
- mutexListeners sync.RWMutex
- srcs []*sourceEntry
- chgListeners []ChangedListener
- shutdown chan interface{}
- wantPanicOnError bool
-}
-
-// PrependSource inserts one or more `Sources` at the beginning of
-// the list of sources such that the first source will be the
-// source checked first when resolving a property value.
-func (config *Config) PrependSource(srcs ...Source) {
- arr := config.wrapSources(srcs...)
-
- config.mutexSrc.Lock()
- if config.shutdown == nil {
- config.shutdown = make(chan interface{})
- }
- config.srcs = append(arr, config.srcs...)
- config.mutexSrc.Unlock()
-
- for _, se := range arr {
- if _, ok := se.src.(SourceMonitored); ok {
- config.monitor(se)
- }
- }
-}
-
-// AppendSource appends one or more `Sources` at the end of
-// the list of sources such that the last source will be the
-// source checked last when resolving a property value.
-func (config *Config) AppendSource(srcs ...Source) {
- arr := config.wrapSources(srcs...)
-
- config.mutexSrc.Lock()
- if config.shutdown == nil {
- config.shutdown = make(chan interface{})
- }
- config.srcs = append(config.srcs, arr...)
- config.mutexSrc.Unlock()
-
- for _, se := range arr {
- if _, ok := se.src.(SourceMonitored); ok {
- config.monitor(se)
- }
- }
-}
-
-// wrapSources wraps one or more Source's and returns
-// them as an array of `sourceEntry`.
-func (config *Config) wrapSources(srcs ...Source) []*sourceEntry {
- arr := make([]*sourceEntry, 0, len(srcs))
- for _, src := range srcs {
- se := &sourceEntry{src: src}
- config.reloadProps(se)
- arr = append(arr, se)
- }
- return arr
-}
-
-// SetWantPanicOnError sets the flag determining if Config
-// should panic when `GetProps` or `GetLastModified` errors
-// for a `Source`.
-func (config *Config) SetWantPanicOnError(b bool) {
- config.mutexSrc.Lock()
- config.wantPanicOnError = b
- config.mutexSrc.Unlock()
-}
-
-// ShouldPanicOnError gets the flag determining if Config
-// should panic when `GetProps` or `GetLastModified` errors
-// for a `Source`.
-func (config *Config) ShouldPanicOnError() (b bool) {
- config.mutexSrc.RLock()
- b = config.wantPanicOnError
- config.mutexSrc.RUnlock()
- return b
-}
-
-// getProp returns the value of a named property.
-// Each `Source` is checked, in the order created by adding via
-// `AppendSource` and `PrependSource`, until a value for the
-// property is found.
-func (config *Config) getProp(name string) (val string, ok bool) {
- config.mutexSrc.RLock()
- defer config.mutexSrc.RUnlock()
-
- var s string
- for _, se := range config.srcs {
- if se.props != nil {
- if s, ok = se.props[name]; ok {
- val = strings.TrimSpace(s)
- return
- }
- }
- }
- return
-}
-
-// String returns the value of the named prop as a string.
-// If the property is not found then the supplied default `def`
-// and `ErrNotFound` are returned.
-func (config *Config) String(name string, def string) (val string, err error) {
- if v, ok := config.getProp(name); ok {
- val = v
- err = nil
- return
- }
-
- err = ErrNotFound
- val = def
- return
-}
-
-// Int returns the value of the named prop as an `int`.
-// If the property is not found then the supplied default `def`
-// and `ErrNotFound` are returned.
-//
-// See config.String
-func (config *Config) Int(name string, def int) (val int, err error) {
- var s string
- if s, err = config.String(name, ""); err == nil {
- var i int64
- if i, err = strconv.ParseInt(s, 10, 32); err == nil {
- val = int(i)
- }
- }
- if err != nil {
- val = def
- }
- return
-}
-
-// Int64 returns the value of the named prop as an `int64`.
-// If the property is not found then the supplied default `def`
-// and `ErrNotFound` are returned.
-//
-// See config.String
-func (config *Config) Int64(name string, def int64) (val int64, err error) {
- var s string
- if s, err = config.String(name, ""); err == nil {
- val, err = strconv.ParseInt(s, 10, 64)
- }
- if err != nil {
- val = def
- }
- return
-}
-
-// Float64 returns the value of the named prop as a `float64`.
-// If the property is not found then the supplied default `def`
-// and `ErrNotFound` are returned.
-//
-// See config.String
-func (config *Config) Float64(name string, def float64) (val float64, err error) {
- var s string
- if s, err = config.String(name, ""); err == nil {
- val, err = strconv.ParseFloat(s, 64)
- }
- if err != nil {
- val = def
- }
- return
-}
-
-// Bool returns the value of the named prop as a `bool`.
-// If the property is not found then the supplied default `def`
-// and `ErrNotFound` are returned.
-//
-// Supports (t, true, 1, y, yes) for true, and (f, false, 0, n, no) for false,
-// all case-insensitive.
-//
-// See config.String
-func (config *Config) Bool(name string, def bool) (val bool, err error) {
- var s string
- if s, err = config.String(name, ""); err == nil {
- switch strings.ToLower(s) {
- case "t", "true", "1", "y", "yes":
- val = true
- case "f", "false", "0", "n", "no":
- val = false
- default:
- err = errors.New("invalid syntax")
- }
- }
- if err != nil {
- val = def
- }
- return
-}
-
-// Duration returns the value of the named prop as a `time.Duration`, representing
-// a span of time.
-//
-// Units of measure are supported: ms, sec, min, hour, day, week, year.
-// See config.UnitsToMillis for a complete list of units supported.
-//
-// If the property is not found then the supplied default `def`
-// and `ErrNotFound` are returned.
-//
-// See config.String
-func (config *Config) Duration(name string, def time.Duration) (val time.Duration, err error) {
- var s string
- if s, err = config.String(name, ""); err == nil {
- var ms int64
- ms, err = timeconv.ParseMilliseconds(s)
- val = time.Duration(ms) * time.Millisecond
- }
- if err != nil {
- val = def
- }
- return
-}
-
-// AddChangedListener adds a listener that will receive notifications
-// whenever one or more property values change within the config.
-func (config *Config) AddChangedListener(l ChangedListener) {
- config.mutexListeners.Lock()
- defer config.mutexListeners.Unlock()
-
- config.chgListeners = append(config.chgListeners, l)
-}
-
-// RemoveChangedListener removes all instances of a ChangedListener.
-// Returns `ErrNotFound` if the listener was not present.
-func (config *Config) RemoveChangedListener(l ChangedListener) error {
- config.mutexListeners.Lock()
- defer config.mutexListeners.Unlock()
-
- dest := make([]ChangedListener, 0, len(config.chgListeners))
- err := ErrNotFound
-
- // Remove all instances of the listener by
- // copying list while filtering.
- for _, s := range config.chgListeners {
- if s != l {
- dest = append(dest, s)
- } else {
- err = nil
- }
- }
- config.chgListeners = dest
- return err
-}
-
-// Shutdown can be called to stop monitoring of all config sources.
-func (config *Config) Shutdown() {
- config.mutexSrc.RLock()
- defer config.mutexSrc.RUnlock()
- if config.shutdown != nil {
- close(config.shutdown)
- }
-}
-
-// onSourceChanged is called whenever one or more properties of a
-// config source has changed.
-func (config *Config) onSourceChanged(src SourceMonitored) {
- defer func() {
- if p := recover(); p != nil {
- fmt.Println(p)
- }
- }()
- config.mutexListeners.RLock()
- defer config.mutexListeners.RUnlock()
- for _, l := range config.chgListeners {
- l.ConfigChanged(config, src)
- }
-}
-
-// monitor periodically checks a config source for changes.
-func (config *Config) monitor(se *sourceEntry) {
- go func(se *sourceEntry, shutdown <-chan interface{}) {
- var src SourceMonitored
- var ok bool
- if src, ok = se.src.(SourceMonitored); !ok {
- return
- }
- paused := false
- last := time.Time{}
- freq := src.GetMonitorFreq()
- if freq <= 0 {
- paused = true
- freq = 10
- last, _ = src.GetLastModified()
- }
- timer := time.NewTimer(freq)
- for {
- select {
- case <-timer.C:
- if !paused {
- if latest, err := src.GetLastModified(); err != nil {
- if config.ShouldPanicOnError() {
- panic(fmt.Sprintf("error <%v> getting last modified for %v", err, src))
- }
- } else {
- if last.Before(latest) {
- last = latest
- config.reloadProps(se)
- // TODO: calc diff and provide detailed changes
- config.onSourceChanged(src)
- }
- }
- }
- freq = src.GetMonitorFreq()
- if freq <= 0 {
- paused = true
- freq = 10
- } else {
- paused = false
- }
- timer.Reset(freq)
- case <-shutdown:
- // stop the timer and exit
- if !timer.Stop() {
- <-timer.C
- }
- return
- }
- }
- }(se, config.shutdown)
-}
-
-// reloadProps causes a Source to reload its properties.
-func (config *Config) reloadProps(se *sourceEntry) {
- config.mutexSrc.Lock()
- defer config.mutexSrc.Unlock()
-
- m, err := se.src.GetProps()
- if err != nil {
- if config.wantPanicOnError {
- panic(fmt.Sprintf("GetProps error for %v", se.src))
- }
- return
- }
-
- se.props = make(map[string]string)
- for k, v := range m {
- se.props[k] = v
- }
-}
diff --git a/vendor/github.com/wiggin77/cfg/go.mod b/vendor/github.com/wiggin77/cfg/go.mod
deleted file mode 100644
index 2e5a038edb..0000000000
--- a/vendor/github.com/wiggin77/cfg/go.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-module github.com/wiggin77/cfg
-
-go 1.12
-
-require github.com/wiggin77/merror v1.0.2
diff --git a/vendor/github.com/wiggin77/cfg/go.sum b/vendor/github.com/wiggin77/cfg/go.sum
deleted file mode 100644
index 30fd3b5809..0000000000
--- a/vendor/github.com/wiggin77/cfg/go.sum
+++ /dev/null
@@ -1,2 +0,0 @@
-github.com/wiggin77/merror v1.0.2 h1:V0nH9eFp64ASyaXC+pB5WpvBoCg7NUwvaCSKdzlcHqw=
-github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg=
diff --git a/vendor/github.com/wiggin77/cfg/ini/ini.go b/vendor/github.com/wiggin77/cfg/ini/ini.go
deleted file mode 100644
index d28d7444dd..0000000000
--- a/vendor/github.com/wiggin77/cfg/ini/ini.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package ini
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "sync"
- "time"
-)
-
-// Ini provides parsing and querying of INI format or simple name/value pairs
-// such as a simple config file.
-// A name/value pair format is just an INI with no sections, and properties can
-// be queried using an empty section name.
-type Ini struct {
- mutex sync.RWMutex
- m map[string]*Section
- lm time.Time
-}
-
-// LoadFromFilespec loads an INI file from string containing path and filename.
-func (ini *Ini) LoadFromFilespec(filespec string) error {
- f, err := os.Open(filespec)
- if err != nil {
- return err
- }
- return ini.LoadFromFile(f)
-}
-
-// LoadFromFile loads an INI file from `os.File`.
-func (ini *Ini) LoadFromFile(file *os.File) error {
-
- fi, err := file.Stat()
- if err != nil {
- return err
- }
- lm := fi.ModTime()
-
- if err := ini.LoadFromReader(file); err != nil {
- return err
- }
- ini.lm = lm
- return nil
-}
-
-// LoadFromReader loads an INI file from an `io.Reader`.
-func (ini *Ini) LoadFromReader(reader io.Reader) error {
- data, err := ioutil.ReadAll(reader)
- if err != nil {
- return err
- }
- return ini.LoadFromString(string(data))
-}
-
-// LoadFromString parses an INI from a string .
-func (ini *Ini) LoadFromString(s string) error {
- m, err := getSections(s)
- if err != nil {
- return err
- }
- ini.mutex.Lock()
- ini.m = m
- ini.lm = time.Now()
- ini.mutex.Unlock()
- return nil
-}
-
-// GetLastModified returns the last modified timestamp of the
-// INI contents.
-func (ini *Ini) GetLastModified() time.Time {
- return ini.lm
-}
-
-// GetSectionNames returns the names of all sections in this INI.
-// Note, the returned section names are a snapshot in time, meaning
-// other goroutines may change the contents of this INI as soon as
-// the method returns.
-func (ini *Ini) GetSectionNames() []string {
- ini.mutex.RLock()
- defer ini.mutex.RUnlock()
-
- arr := make([]string, 0, len(ini.m))
- for key := range ini.m {
- arr = append(arr, key)
- }
- return arr
-}
-
-// GetKeys returns the names of all keys in the specified section.
-// Note, the returned key names are a snapshot in time, meaning other
-// goroutines may change the contents of this INI as soon as the
-// method returns.
-func (ini *Ini) GetKeys(sectionName string) ([]string, error) {
- sec, err := ini.getSection(sectionName)
- if err != nil {
- return nil, err
- }
- return sec.getKeys(), nil
-}
-
-// getSection returns the named section.
-func (ini *Ini) getSection(sectionName string) (*Section, error) {
- ini.mutex.RLock()
- defer ini.mutex.RUnlock()
-
- sec, ok := ini.m[sectionName]
- if !ok {
- return nil, fmt.Errorf("section '%s' not found", sectionName)
- }
- return sec, nil
-}
-
-// GetFlattenedKeys returns all section names plus keys as one
-// flattened array.
-func (ini *Ini) GetFlattenedKeys() []string {
- ini.mutex.RLock()
- defer ini.mutex.RUnlock()
-
- arr := make([]string, 0, len(ini.m)*2)
- for _, section := range ini.m {
- keys := section.getKeys()
- for _, key := range keys {
- name := section.GetName()
- if name != "" {
- key = name + "." + key
- }
- arr = append(arr, key)
- }
- }
- return arr
-}
-
-// GetProp returns the value of the specified key in the named section.
-func (ini *Ini) GetProp(section string, key string) (val string, ok bool) {
- sec, err := ini.getSection(section)
- if err != nil {
- return val, false
- }
- return sec.GetProp(key)
-}
-
-// ToMap returns a flattened map of the section name plus keys mapped
-// to values.
-func (ini *Ini) ToMap() map[string]string {
- m := make(map[string]string)
-
- ini.mutex.RLock()
- defer ini.mutex.RUnlock()
-
- for _, section := range ini.m {
- for _, key := range section.getKeys() {
- val, ok := section.GetProp(key)
- if ok {
- name := section.GetName()
- var mapkey string
- if name != "" {
- mapkey = name + "." + key
- } else {
- mapkey = key
- }
- m[mapkey] = val
- }
- }
- }
- return m
-}
diff --git a/vendor/github.com/wiggin77/cfg/ini/parser.go b/vendor/github.com/wiggin77/cfg/ini/parser.go
deleted file mode 100644
index 28916409ae..0000000000
--- a/vendor/github.com/wiggin77/cfg/ini/parser.go
+++ /dev/null
@@ -1,142 +0,0 @@
-package ini
-
-import (
- "fmt"
- "strings"
-
- "github.com/wiggin77/merror"
-)
-
-// LF is linefeed
-const LF byte = 0x0A
-
-// CR is carriage return
-const CR byte = 0x0D
-
-// getSections parses an INI formatted string, or string containing just name/value pairs,
-// returns map of `Section`'s.
-//
-// Any name/value pairs appearing before a section name are added to the section named
-// with an empty string (""). Also true for Linux-style config files where all props
-// are outside a named section.
-//
-// Any errors encountered are aggregated and returned, along with the partially parsed
-// sections.
-func getSections(str string) (map[string]*Section, error) {
- merr := merror.New()
- mapSections := make(map[string]*Section)
- lines := buildLineArray(str)
- section := newSection("")
-
- for _, line := range lines {
- name, ok := parseSection(line)
- if ok {
- // A section name encountered. Stop processing the current one.
- // Don't add the current section to the map if the section name is blank
- // and the prop map is empty.
- nameCurr := section.GetName()
- if nameCurr != "" || section.hasKeys() {
- mapSections[nameCurr] = section
- }
- // Start processing a new section.
- section = newSection(name)
- } else {
- // Parse the property and add to the current section, or ignore if comment.
- if k, v, comment, err := parseProp(line); !comment && err == nil {
- section.setProp(k, v)
- } else if err != nil {
- merr.Append(err) // aggregate errors
- }
- }
-
- }
- // If the current section is not empty, add it.
- if section.hasKeys() {
- mapSections[section.GetName()] = section
- }
- return mapSections, merr.ErrorOrNil()
-}
-
-// buildLineArray parses the given string buffer and creates a list of strings,
-// one for each line in the string buffer.
-//
-// A line is considered to be terminated by any one of a line feed ('\n'),
-// a carriage return ('\r'), or a carriage return followed immediately by a
-// linefeed.
-//
-// Lines prefixed with ';' or '#' are considered comments and skipped.
-func buildLineArray(str string) []string {
- arr := make([]string, 0, 10)
- str = str + "\n"
-
- iLen := len(str)
- iPos, iBegin := 0, 0
- var ch byte
-
- for iPos < iLen {
- ch = str[iPos]
- if ch == LF || ch == CR {
- sub := str[iBegin:iPos]
- sub = strings.TrimSpace(sub)
- if sub != "" && !strings.HasPrefix(sub, ";") && !strings.HasPrefix(sub, "#") {
- arr = append(arr, sub)
- }
- iPos++
- if ch == CR && iPos < iLen && str[iPos] == LF {
- iPos++
- }
- iBegin = iPos
- } else {
- iPos++
- }
- }
- return arr
-}
-
-// parseSection parses the specified string for a section name enclosed in square brackets.
-// Returns the section name found, or `ok=false` if `str` is not a section header.
-func parseSection(str string) (name string, ok bool) {
- str = strings.TrimSpace(str)
- if !strings.HasPrefix(str, "[") {
- return "", false
- }
- iCloser := strings.Index(str, "]")
- if iCloser == -1 {
- return "", false
- }
- return strings.TrimSpace(str[1:iCloser]), true
-}
-
-// parseProp parses the specified string and extracts a key/value pair.
-//
-// If the string is a comment (prefixed with ';' or '#') then `comment=true`
-// and key will be empty.
-func parseProp(str string) (key string, val string, comment bool, err error) {
- iLen := len(str)
- iEqPos := strings.Index(str, "=")
- if iEqPos == -1 {
- return "", "", false, fmt.Errorf("not a key/value pair:'%s'", str)
- }
-
- key = str[0:iEqPos]
- key = strings.TrimSpace(key)
- if iEqPos+1 < iLen {
- val = str[iEqPos+1:]
- val = strings.TrimSpace(val)
- }
-
- // Check that the key has at least 1 char.
- if key == "" {
- return "", "", false, fmt.Errorf("key is empty for '%s'", str)
- }
-
- // Check if this line is a comment that just happens
- // to have an equals sign in it. Not an error, but not a
- // useable line either.
- if strings.HasPrefix(key, ";") || strings.HasPrefix(key, "#") {
- key = ""
- val = ""
- comment = true
- }
- return key, val, comment, err
-}
diff --git a/vendor/github.com/wiggin77/cfg/ini/section.go b/vendor/github.com/wiggin77/cfg/ini/section.go
deleted file mode 100644
index 18c4c25403..0000000000
--- a/vendor/github.com/wiggin77/cfg/ini/section.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package ini
-
-import (
- "fmt"
- "strings"
- "sync"
-)
-
-// Section represents a section in an INI file. The section has a name, which is
-// enclosed in square brackets in the file. The section also has an array of
-// key/value pairs.
-type Section struct {
- name string
- props map[string]string
- mtx sync.RWMutex
-}
-
-func newSection(name string) *Section {
- sec := &Section{}
- sec.name = name
- sec.props = make(map[string]string)
- return sec
-}
-
-// addLines addes an array of strings containing name/value pairs
-// of the format `key=value`.
-//func addLines(lines []string) {
-// TODO
-//}
-
-// GetName returns the name of the section.
-func (sec *Section) GetName() (name string) {
- sec.mtx.RLock()
- name = sec.name
- sec.mtx.RUnlock()
- return
-}
-
-// GetProp returns the value associated with the given key, or
-// `ok=false` if key does not exist.
-func (sec *Section) GetProp(key string) (val string, ok bool) {
- sec.mtx.RLock()
- val, ok = sec.props[key]
- sec.mtx.RUnlock()
- return
-}
-
-// SetProp sets the value associated with the given key.
-func (sec *Section) setProp(key string, val string) {
- sec.mtx.Lock()
- sec.props[key] = val
- sec.mtx.Unlock()
-}
-
-// hasKeys returns true if there are one or more properties in
-// this section.
-func (sec *Section) hasKeys() (b bool) {
- sec.mtx.RLock()
- b = len(sec.props) > 0
- sec.mtx.RUnlock()
- return
-}
-
-// getKeys returns an array containing all keys in this section.
-func (sec *Section) getKeys() []string {
- sec.mtx.RLock()
- defer sec.mtx.RUnlock()
-
- arr := make([]string, len(sec.props))
- idx := 0
- for k := range sec.props {
- arr[idx] = k
- idx++
- }
- return arr
-}
-
-// combine the given section with this one.
-func (sec *Section) combine(sec2 *Section) {
- sec.mtx.Lock()
- sec2.mtx.RLock()
- defer sec.mtx.Unlock()
- defer sec2.mtx.RUnlock()
-
- for k, v := range sec2.props {
- sec.props[k] = v
- }
-}
-
-// String returns a string representation of this section.
-func (sec *Section) String() string {
- return fmt.Sprintf("[%s]\n%s", sec.GetName(), sec.StringPropsOnly())
-}
-
-// StringPropsOnly returns a string representation of this section
-// without the section header.
-func (sec *Section) StringPropsOnly() string {
- sec.mtx.RLock()
- defer sec.mtx.RUnlock()
- sb := &strings.Builder{}
-
- for k, v := range sec.props {
- sb.WriteString(k)
- sb.WriteString("=")
- sb.WriteString(v)
- sb.WriteString("\n")
- }
- return sb.String()
-}
diff --git a/vendor/github.com/wiggin77/cfg/listener.go b/vendor/github.com/wiggin77/cfg/listener.go
deleted file mode 100644
index 12ea4e45d6..0000000000
--- a/vendor/github.com/wiggin77/cfg/listener.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package cfg
-
-// ChangedListener interface is for receiving notifications
-// when one or more properties within monitored config sources
-// (SourceMonitored) have changed values.
-type ChangedListener interface {
-
- // Changed is called when one or more properties in a `SourceMonitored` has a
- // changed value.
- ConfigChanged(cfg *Config, src SourceMonitored)
-}
diff --git a/vendor/github.com/wiggin77/cfg/nocopy.go b/vendor/github.com/wiggin77/cfg/nocopy.go
deleted file mode 100644
index f2450c0b23..0000000000
--- a/vendor/github.com/wiggin77/cfg/nocopy.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package cfg
-
-// noCopy may be embedded into structs which must not be copied
-// after the first use.
-//
-// See https://golang.org/issues/8005#issuecomment-190753527
-// for details.
-type noCopy struct{}
-
-// Lock is a no-op used by -copylocks checker from `go vet`.
-func (*noCopy) Lock() {}
diff --git a/vendor/github.com/wiggin77/cfg/source.go b/vendor/github.com/wiggin77/cfg/source.go
deleted file mode 100644
index 09083e970e..0000000000
--- a/vendor/github.com/wiggin77/cfg/source.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package cfg
-
-import (
- "sync"
- "time"
-)
-
-// Source is the interface required for any source of name/value pairs.
-type Source interface {
-
- // GetProps fetches all the properties from a source and returns
- // them as a map.
- GetProps() (map[string]string, error)
-}
-
-// SourceMonitored is the interface required for any config source that is
-// monitored for changes.
-type SourceMonitored interface {
- Source
-
- // GetLastModified returns the time of the latest modification to any
- // property value within the source. If a source does not support
- // modifying properties at runtime then the zero value for `Time`
- // should be returned to ensure reload events are not generated.
- GetLastModified() (time.Time, error)
-
- // GetMonitorFreq returns the frequency as a `time.Duration` between
- // checks for changes to this config source.
- //
- // Returning zero (or less) will temporarily suspend calls to `GetLastModified`
- // and `GetMonitorFreq` will be called every 10 seconds until resumed, after which
- // `GetMontitorFreq` will be called at a frequency roughly equal to the `time.Duration`
- // returned.
- GetMonitorFreq() time.Duration
-}
-
-// AbstractSourceMonitor can be embedded in a custom `Source` to provide the
-// basic plumbing for monitor frequency.
-type AbstractSourceMonitor struct {
- mutex sync.RWMutex
- freq time.Duration
-}
-
-// GetMonitorFreq returns the frequency as a `time.Duration` between
-// checks for changes to this config source.
-func (asm *AbstractSourceMonitor) GetMonitorFreq() (freq time.Duration) {
- asm.mutex.RLock()
- freq = asm.freq
- asm.mutex.RUnlock()
- return
-}
-
-// SetMonitorFreq sets the frequency between checks for changes to this config source.
-func (asm *AbstractSourceMonitor) SetMonitorFreq(freq time.Duration) {
- asm.mutex.Lock()
- asm.freq = freq
- asm.mutex.Unlock()
-}
diff --git a/vendor/github.com/wiggin77/cfg/srcfile.go b/vendor/github.com/wiggin77/cfg/srcfile.go
deleted file mode 100644
index f42c69fac7..0000000000
--- a/vendor/github.com/wiggin77/cfg/srcfile.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package cfg
-
-import (
- "os"
- "time"
-
- "github.com/wiggin77/cfg/ini"
-)
-
-// SrcFile is a configuration `Source` backed by a file containing
-// name/value pairs or INI format.
-type SrcFile struct {
- AbstractSourceMonitor
- ini ini.Ini
- file *os.File
-}
-
-// NewSrcFileFromFilespec creates a new SrcFile with the specified filespec.
-func NewSrcFileFromFilespec(filespec string) (*SrcFile, error) {
- file, err := os.Open(filespec)
- if err != nil {
- return nil, err
- }
- return NewSrcFile(file)
-}
-
-// NewSrcFile creates a new SrcFile with the specified os.File.
-func NewSrcFile(file *os.File) (*SrcFile, error) {
- sf := &SrcFile{}
- sf.freq = time.Minute
- sf.file = file
- if err := sf.ini.LoadFromFile(file); err != nil {
- return nil, err
- }
- return sf, nil
-}
-
-// GetProps fetches all the properties from a source and returns
-// them as a map.
-func (sf *SrcFile) GetProps() (map[string]string, error) {
- lm, err := sf.GetLastModified()
- if err != nil {
- return nil, err
- }
-
- // Check if we need to reload.
- if sf.ini.GetLastModified() != lm {
- if err := sf.ini.LoadFromFile(sf.file); err != nil {
- return nil, err
- }
- }
- return sf.ini.ToMap(), nil
-}
-
-// GetLastModified returns the time of the latest modification to any
-// property value within the source.
-func (sf *SrcFile) GetLastModified() (time.Time, error) {
- fi, err := sf.file.Stat()
- if err != nil {
- return time.Now(), err
- }
- return fi.ModTime(), nil
-}
diff --git a/vendor/github.com/wiggin77/cfg/srcmap.go b/vendor/github.com/wiggin77/cfg/srcmap.go
deleted file mode 100644
index 321db27ac9..0000000000
--- a/vendor/github.com/wiggin77/cfg/srcmap.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package cfg
-
-import (
- "time"
-)
-
-// SrcMap is a configuration `Source` backed by a simple map.
-type SrcMap struct {
- AbstractSourceMonitor
- m map[string]string
- lm time.Time
-}
-
-// NewSrcMap creates an empty `SrcMap`.
-func NewSrcMap() *SrcMap {
- sm := &SrcMap{}
- sm.m = make(map[string]string)
- sm.lm = time.Now()
- sm.freq = time.Minute
- return sm
-}
-
-// NewSrcMapFromMap creates a `SrcMap` containing a copy of the
-// specified map.
-func NewSrcMapFromMap(mapIn map[string]string) *SrcMap {
- sm := NewSrcMap()
- sm.PutAll(mapIn)
- return sm
-}
-
-// Put inserts or updates a value in the `SrcMap`.
-func (sm *SrcMap) Put(key string, val string) {
- sm.mutex.Lock()
- sm.m[key] = val
- sm.lm = time.Now()
- sm.mutex.Unlock()
-}
-
-// PutAll inserts a copy of `mapIn` into the `SrcMap`
-func (sm *SrcMap) PutAll(mapIn map[string]string) {
- sm.mutex.Lock()
- defer sm.mutex.Unlock()
-
- for k, v := range mapIn {
- sm.m[k] = v
- }
- sm.lm = time.Now()
-}
-
-// GetProps fetches all the properties from a source and returns
-// them as a map.
-func (sm *SrcMap) GetProps() (m map[string]string, err error) {
- sm.mutex.RLock()
- m = sm.m
- sm.mutex.RUnlock()
- return
-}
-
-// GetLastModified returns the time of the latest modification to any
-// property value within the source. If a source does not support
-// modifying properties at runtime then the zero value for `Time`
-// should be returned to ensure reload events are not generated.
-func (sm *SrcMap) GetLastModified() (last time.Time, err error) {
- sm.mutex.RLock()
- last = sm.lm
- sm.mutex.RUnlock()
- return
-}
-
-// GetMonitorFreq returns the frequency as a `time.Duration` between
-// checks for changes to this config source. Defaults to 1 minute
-// unless changed with `SetMonitorFreq`.
-func (sm *SrcMap) GetMonitorFreq() (freq time.Duration) {
- sm.mutex.RLock()
- freq = sm.freq
- sm.mutex.RUnlock()
- return
-}
diff --git a/vendor/github.com/wiggin77/cfg/timeconv/parse.go b/vendor/github.com/wiggin77/cfg/timeconv/parse.go
deleted file mode 100644
index 218ef43a04..0000000000
--- a/vendor/github.com/wiggin77/cfg/timeconv/parse.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package timeconv
-
-import (
- "fmt"
- "math"
- "regexp"
- "strconv"
- "strings"
-)
-
-// MillisPerSecond is the number of millseconds per second.
-const MillisPerSecond int64 = 1000
-
-// MillisPerMinute is the number of millseconds per minute.
-const MillisPerMinute int64 = MillisPerSecond * 60
-
-// MillisPerHour is the number of millseconds per hour.
-const MillisPerHour int64 = MillisPerMinute * 60
-
-// MillisPerDay is the number of millseconds per day.
-const MillisPerDay int64 = MillisPerHour * 24
-
-// MillisPerWeek is the number of millseconds per week.
-const MillisPerWeek int64 = MillisPerDay * 7
-
-// MillisPerYear is the approximate number of millseconds per year.
-const MillisPerYear int64 = MillisPerDay*365 + int64((float64(MillisPerDay) * 0.25))
-
-// ParseMilliseconds parses a string containing a number plus
-// a unit of measure for time and returns the number of milliseconds
-// it represents.
-//
-// Example:
-// * "1 second" returns 1000
-// * "1 minute" returns 60000
-// * "1 hour" returns 3600000
-//
-// See config.UnitsToMillis for a list of supported units of measure.
-func ParseMilliseconds(str string) (int64, error) {
- s := strings.TrimSpace(str)
- reg := regexp.MustCompile("([0-9\\.\\-+]*)(.*)")
- matches := reg.FindStringSubmatch(s)
- if matches == nil || len(matches) < 1 || matches[1] == "" {
- return 0, fmt.Errorf("invalid syntax - '%s'", s)
- }
- digits := matches[1]
- units := "ms"
- if len(matches) > 1 && matches[2] != "" {
- units = matches[2]
- }
-
- fDigits, err := strconv.ParseFloat(digits, 64)
- if err != nil {
- return 0, err
- }
-
- msPerUnit, err := UnitsToMillis(units)
- if err != nil {
- return 0, err
- }
-
- // Check for overflow.
- fms := float64(msPerUnit) * fDigits
- if fms > math.MaxInt64 || fms < math.MinInt64 {
- return 0, fmt.Errorf("out of range - '%s' overflows", s)
- }
- ms := int64(fms)
- return ms, nil
-}
-
-// UnitsToMillis returns the number of milliseconds represented by the specified unit of measure.
-//
-// Example:
-// * "second" returns 1000
-// * "minute" returns 60000
-// * "hour" returns 3600000
-//
-// Supported units of measure:
-// * "milliseconds", "millis", "ms", "millisecond"
-// * "seconds", "sec", "s", "second"
-// * "minutes", "mins", "min", "m", "minute"
-// * "hours", "h", "hour"
-// * "days", "d", "day"
-// * "weeks", "w", "week"
-// * "years", "y", "year"
-func UnitsToMillis(units string) (ms int64, err error) {
- u := strings.TrimSpace(units)
- u = strings.ToLower(u)
- switch u {
- case "milliseconds", "millisecond", "millis", "ms":
- ms = 1
- case "seconds", "second", "sec", "s":
- ms = MillisPerSecond
- case "minutes", "minute", "mins", "min", "m":
- ms = MillisPerMinute
- case "hours", "hour", "h":
- ms = MillisPerHour
- case "days", "day", "d":
- ms = MillisPerDay
- case "weeks", "week", "w":
- ms = MillisPerWeek
- case "years", "year", "y":
- ms = MillisPerYear
- default:
- err = fmt.Errorf("invalid syntax - '%s' not a supported unit of measure", u)
- }
- return
-}
diff --git a/vendor/go.uber.org/multierr/.codecov.yml b/vendor/go.uber.org/multierr/.codecov.yml
deleted file mode 100644
index 6d4d1be7b5..0000000000
--- a/vendor/go.uber.org/multierr/.codecov.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-coverage:
- range: 80..100
- round: down
- precision: 2
-
- status:
- project: # measuring the overall project coverage
- default: # context, you can create multiple ones with custom titles
- enabled: yes # must be yes|true to enable this status
- target: 100 # specify the target coverage for each commit status
- # option: "auto" (must increase from parent commit or pull request base)
- # option: "X%" a static target percentage to hit
- if_not_found: success # if parent is not found report status as success, error, or failure
- if_ci_failed: error # if ci fails report status as success, error, or failure
-
diff --git a/vendor/go.uber.org/multierr/.gitignore b/vendor/go.uber.org/multierr/.gitignore
deleted file mode 100644
index b9a05e3da0..0000000000
--- a/vendor/go.uber.org/multierr/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/vendor
-cover.html
-cover.out
-/bin
diff --git a/vendor/go.uber.org/multierr/CHANGELOG.md b/vendor/go.uber.org/multierr/CHANGELOG.md
deleted file mode 100644
index b0814e7c9b..0000000000
--- a/vendor/go.uber.org/multierr/CHANGELOG.md
+++ /dev/null
@@ -1,66 +0,0 @@
-Releases
-========
-
-v1.7.0 (2021-05-06)
-===================
-
-- Add `AppendInvoke` to append into errors from `defer` blocks.
-
-
-v1.6.0 (2020-09-14)
-===================
-
-- Actually drop library dependency on development-time tooling.
-
-
-v1.5.0 (2020-02-24)
-===================
-
-- Drop library dependency on development-time tooling.
-
-
-v1.4.0 (2019-11-04)
-===================
-
-- Add `AppendInto` function to more ergonomically build errors inside a
- loop.
-
-
-v1.3.0 (2019-10-29)
-===================
-
-- Switch to Go modules.
-
-
-v1.2.0 (2019-09-26)
-===================
-
-- Support extracting and matching against wrapped errors with `errors.As`
- and `errors.Is`.
-
-
-v1.1.0 (2017-06-30)
-===================
-
-- Added an `Errors(error) []error` function to extract the underlying list of
- errors for a multierr error.
-
-
-v1.0.0 (2017-05-31)
-===================
-
-No changes since v0.2.0. This release is committing to making no breaking
-changes to the current API in the 1.X series.
-
-
-v0.2.0 (2017-04-11)
-===================
-
-- Repeatedly appending to the same error is now faster due to fewer
- allocations.
-
-
-v0.1.0 (2017-31-03)
-===================
-
-- Initial release
diff --git a/vendor/go.uber.org/multierr/LICENSE.txt b/vendor/go.uber.org/multierr/LICENSE.txt
deleted file mode 100644
index 413e30f7ce..0000000000
--- a/vendor/go.uber.org/multierr/LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2017-2021 Uber Technologies, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/vendor/go.uber.org/multierr/Makefile b/vendor/go.uber.org/multierr/Makefile
deleted file mode 100644
index dcb6fe723c..0000000000
--- a/vendor/go.uber.org/multierr/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-# Directory to put `go install`ed binaries in.
-export GOBIN ?= $(shell pwd)/bin
-
-GO_FILES := $(shell \
- find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
- -o -name '*.go' -print | cut -b3-)
-
-.PHONY: build
-build:
- go build ./...
-
-.PHONY: test
-test:
- go test -race ./...
-
-.PHONY: gofmt
-gofmt:
- $(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX))
- @gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true
- @[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" | cat - $(FMT_LOG) && false)
-
-.PHONY: golint
-golint:
- @cd tools && go install golang.org/x/lint/golint
- @$(GOBIN)/golint ./...
-
-.PHONY: staticcheck
-staticcheck:
- @cd tools && go install honnef.co/go/tools/cmd/staticcheck
- @$(GOBIN)/staticcheck ./...
-
-.PHONY: lint
-lint: gofmt golint staticcheck
-
-.PHONY: cover
-cover:
- go test -race -coverprofile=cover.out -coverpkg=./... -v ./...
- go tool cover -html=cover.out -o cover.html
diff --git a/vendor/go.uber.org/multierr/README.md b/vendor/go.uber.org/multierr/README.md
deleted file mode 100644
index 70aacecd71..0000000000
--- a/vendor/go.uber.org/multierr/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# multierr [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
-
-`multierr` allows combining one or more Go `error`s together.
-
-## Installation
-
- go get -u go.uber.org/multierr
-
-## Status
-
-Stable: No breaking changes will be made before 2.0.
-
--------------------------------------------------------------------------------
-
-Released under the [MIT License].
-
-[MIT License]: LICENSE.txt
-[doc-img]: https://pkg.go.dev/badge/go.uber.org/multierr
-[doc]: https://pkg.go.dev/go.uber.org/multierr
-[ci-img]: https://github.com/uber-go/multierr/actions/workflows/go.yml/badge.svg
-[cov-img]: https://codecov.io/gh/uber-go/multierr/branch/master/graph/badge.svg
-[ci]: https://github.com/uber-go/multierr/actions/workflows/go.yml
-[cov]: https://codecov.io/gh/uber-go/multierr
diff --git a/vendor/go.uber.org/multierr/error.go b/vendor/go.uber.org/multierr/error.go
deleted file mode 100644
index faa0a05946..0000000000
--- a/vendor/go.uber.org/multierr/error.go
+++ /dev/null
@@ -1,639 +0,0 @@
-// Copyright (c) 2017-2021 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package multierr allows combining one or more errors together.
-//
-// Overview
-//
-// Errors can be combined with the use of the Combine function.
-//
-// multierr.Combine(
-// reader.Close(),
-// writer.Close(),
-// conn.Close(),
-// )
-//
-// If only two errors are being combined, the Append function may be used
-// instead.
-//
-// err = multierr.Append(reader.Close(), writer.Close())
-//
-// The underlying list of errors for a returned error object may be retrieved
-// with the Errors function.
-//
-// errors := multierr.Errors(err)
-// if len(errors) > 0 {
-// fmt.Println("The following errors occurred:", errors)
-// }
-//
-// Appending from a loop
-//
-// You sometimes need to append into an error from a loop.
-//
-// var err error
-// for _, item := range items {
-// err = multierr.Append(err, process(item))
-// }
-//
-// Cases like this may require knowledge of whether an individual instance
-// failed. This usually requires introduction of a new variable.
-//
-// var err error
-// for _, item := range items {
-// if perr := process(item); perr != nil {
-// log.Warn("skipping item", item)
-// err = multierr.Append(err, perr)
-// }
-// }
-//
-// multierr includes AppendInto to simplify cases like this.
-//
-// var err error
-// for _, item := range items {
-// if multierr.AppendInto(&err, process(item)) {
-// log.Warn("skipping item", item)
-// }
-// }
-//
-// This will append the error into the err variable, and return true if that
-// individual error was non-nil.
-//
-// See AppendInto for more information.
-//
-// Deferred Functions
-//
-// Go makes it possible to modify the return value of a function in a defer
-// block if the function was using named returns. This makes it possible to
-// record resource cleanup failures from deferred blocks.
-//
-// func sendRequest(req Request) (err error) {
-// conn, err := openConnection()
-// if err != nil {
-// return err
-// }
-// defer func() {
-// err = multierr.Append(err, conn.Close())
-// }()
-// // ...
-// }
-//
-// multierr provides the Invoker type and AppendInvoke function to make cases
-// like the above simpler and obviate the need for a closure. The following is
-// roughly equivalent to the example above.
-//
-// func sendRequest(req Request) (err error) {
-// conn, err := openConnection()
-// if err != nil {
-// return err
-// }
-// defer multierr.AppendInvoke(err, multierr.Close(conn))
-// // ...
-// }
-//
-// See AppendInvoke and Invoker for more information.
-//
-// Advanced Usage
-//
-// Errors returned by Combine and Append MAY implement the following
-// interface.
-//
-// type errorGroup interface {
-// // Returns a slice containing the underlying list of errors.
-// //
-// // This slice MUST NOT be modified by the caller.
-// Errors() []error
-// }
-//
-// Note that if you need access to list of errors behind a multierr error, you
-// should prefer using the Errors function. That said, if you need cheap
-// read-only access to the underlying errors slice, you can attempt to cast
-// the error to this interface. You MUST handle the failure case gracefully
-// because errors returned by Combine and Append are not guaranteed to
-// implement this interface.
-//
-// var errors []error
-// group, ok := err.(errorGroup)
-// if ok {
-// errors = group.Errors()
-// } else {
-// errors = []error{err}
-// }
-package multierr // import "go.uber.org/multierr"
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "strings"
- "sync"
-
- "go.uber.org/atomic"
-)
-
-var (
- // Separator for single-line error messages.
- _singlelineSeparator = []byte("; ")
-
- // Prefix for multi-line messages
- _multilinePrefix = []byte("the following errors occurred:")
-
- // Prefix for the first and following lines of an item in a list of
- // multi-line error messages.
- //
- // For example, if a single item is:
- //
- // foo
- // bar
- //
- // It will become,
- //
- // - foo
- // bar
- _multilineSeparator = []byte("\n - ")
- _multilineIndent = []byte(" ")
-)
-
-// _bufferPool is a pool of bytes.Buffers.
-var _bufferPool = sync.Pool{
- New: func() interface{} {
- return &bytes.Buffer{}
- },
-}
-
-type errorGroup interface {
- Errors() []error
-}
-
-// Errors returns a slice containing zero or more errors that the supplied
-// error is composed of. If the error is nil, a nil slice is returned.
-//
-// err := multierr.Append(r.Close(), w.Close())
-// errors := multierr.Errors(err)
-//
-// If the error is not composed of other errors, the returned slice contains
-// just the error that was passed in.
-//
-// Callers of this function are free to modify the returned slice.
-func Errors(err error) []error {
- if err == nil {
- return nil
- }
-
- // Note that we're casting to multiError, not errorGroup. Our contract is
- // that returned errors MAY implement errorGroup. Errors, however, only
- // has special behavior for multierr-specific error objects.
- //
- // This behavior can be expanded in the future but I think it's prudent to
- // start with as little as possible in terms of contract and possibility
- // of misuse.
- eg, ok := err.(*multiError)
- if !ok {
- return []error{err}
- }
-
- errors := eg.Errors()
- result := make([]error, len(errors))
- copy(result, errors)
- return result
-}
-
-// multiError is an error that holds one or more errors.
-//
-// An instance of this is guaranteed to be non-empty and flattened. That is,
-// none of the errors inside multiError are other multiErrors.
-//
-// multiError formats to a semi-colon delimited list of error messages with
-// %v and with a more readable multi-line format with %+v.
-type multiError struct {
- copyNeeded atomic.Bool
- errors []error
-}
-
-var _ errorGroup = (*multiError)(nil)
-
-// Errors returns the list of underlying errors.
-//
-// This slice MUST NOT be modified.
-func (merr *multiError) Errors() []error {
- if merr == nil {
- return nil
- }
- return merr.errors
-}
-
-// As attempts to find the first error in the error list that matches the type
-// of the value that target points to.
-//
-// This function allows errors.As to traverse the values stored on the
-// multierr error.
-func (merr *multiError) As(target interface{}) bool {
- for _, err := range merr.Errors() {
- if errors.As(err, target) {
- return true
- }
- }
- return false
-}
-
-// Is attempts to match the provided error against errors in the error list.
-//
-// This function allows errors.Is to traverse the values stored on the
-// multierr error.
-func (merr *multiError) Is(target error) bool {
- for _, err := range merr.Errors() {
- if errors.Is(err, target) {
- return true
- }
- }
- return false
-}
-
-func (merr *multiError) Error() string {
- if merr == nil {
- return ""
- }
-
- buff := _bufferPool.Get().(*bytes.Buffer)
- buff.Reset()
-
- merr.writeSingleline(buff)
-
- result := buff.String()
- _bufferPool.Put(buff)
- return result
-}
-
-func (merr *multiError) Format(f fmt.State, c rune) {
- if c == 'v' && f.Flag('+') {
- merr.writeMultiline(f)
- } else {
- merr.writeSingleline(f)
- }
-}
-
-func (merr *multiError) writeSingleline(w io.Writer) {
- first := true
- for _, item := range merr.errors {
- if first {
- first = false
- } else {
- w.Write(_singlelineSeparator)
- }
- io.WriteString(w, item.Error())
- }
-}
-
-func (merr *multiError) writeMultiline(w io.Writer) {
- w.Write(_multilinePrefix)
- for _, item := range merr.errors {
- w.Write(_multilineSeparator)
- writePrefixLine(w, _multilineIndent, fmt.Sprintf("%+v", item))
- }
-}
-
-// Writes s to the writer with the given prefix added before each line after
-// the first.
-func writePrefixLine(w io.Writer, prefix []byte, s string) {
- first := true
- for len(s) > 0 {
- if first {
- first = false
- } else {
- w.Write(prefix)
- }
-
- idx := strings.IndexByte(s, '\n')
- if idx < 0 {
- idx = len(s) - 1
- }
-
- io.WriteString(w, s[:idx+1])
- s = s[idx+1:]
- }
-}
-
-type inspectResult struct {
- // Number of top-level non-nil errors
- Count int
-
- // Total number of errors including multiErrors
- Capacity int
-
- // Index of the first non-nil error in the list. Value is meaningless if
- // Count is zero.
- FirstErrorIdx int
-
- // Whether the list contains at least one multiError
- ContainsMultiError bool
-}
-
-// Inspects the given slice of errors so that we can efficiently allocate
-// space for it.
-func inspect(errors []error) (res inspectResult) {
- first := true
- for i, err := range errors {
- if err == nil {
- continue
- }
-
- res.Count++
- if first {
- first = false
- res.FirstErrorIdx = i
- }
-
- if merr, ok := err.(*multiError); ok {
- res.Capacity += len(merr.errors)
- res.ContainsMultiError = true
- } else {
- res.Capacity++
- }
- }
- return
-}
-
-// fromSlice converts the given list of errors into a single error.
-func fromSlice(errors []error) error {
- res := inspect(errors)
- switch res.Count {
- case 0:
- return nil
- case 1:
- // only one non-nil entry
- return errors[res.FirstErrorIdx]
- case len(errors):
- if !res.ContainsMultiError {
- // already flat
- return &multiError{errors: errors}
- }
- }
-
- nonNilErrs := make([]error, 0, res.Capacity)
- for _, err := range errors[res.FirstErrorIdx:] {
- if err == nil {
- continue
- }
-
- if nested, ok := err.(*multiError); ok {
- nonNilErrs = append(nonNilErrs, nested.errors...)
- } else {
- nonNilErrs = append(nonNilErrs, err)
- }
- }
-
- return &multiError{errors: nonNilErrs}
-}
-
-// Combine combines the passed errors into a single error.
-//
-// If zero arguments were passed or if all items are nil, a nil error is
-// returned.
-//
-// Combine(nil, nil) // == nil
-//
-// If only a single error was passed, it is returned as-is.
-//
-// Combine(err) // == err
-//
-// Combine skips over nil arguments so this function may be used to combine
-// together errors from operations that fail independently of each other.
-//
-// multierr.Combine(
-// reader.Close(),
-// writer.Close(),
-// pipe.Close(),
-// )
-//
-// If any of the passed errors is a multierr error, it will be flattened along
-// with the other errors.
-//
-// multierr.Combine(multierr.Combine(err1, err2), err3)
-// // is the same as
-// multierr.Combine(err1, err2, err3)
-//
-// The returned error formats into a readable multi-line error message if
-// formatted with %+v.
-//
-// fmt.Sprintf("%+v", multierr.Combine(err1, err2))
-func Combine(errors ...error) error {
- return fromSlice(errors)
-}
-
-// Append appends the given errors together. Either value may be nil.
-//
-// This function is a specialization of Combine for the common case where
-// there are only two errors.
-//
-// err = multierr.Append(reader.Close(), writer.Close())
-//
-// The following pattern may also be used to record failure of deferred
-// operations without losing information about the original error.
-//
-// func doSomething(..) (err error) {
-// f := acquireResource()
-// defer func() {
-// err = multierr.Append(err, f.Close())
-// }()
-func Append(left error, right error) error {
- switch {
- case left == nil:
- return right
- case right == nil:
- return left
- }
-
- if _, ok := right.(*multiError); !ok {
- if l, ok := left.(*multiError); ok && !l.copyNeeded.Swap(true) {
- // Common case where the error on the left is constantly being
- // appended to.
- errs := append(l.errors, right)
- return &multiError{errors: errs}
- } else if !ok {
- // Both errors are single errors.
- return &multiError{errors: []error{left, right}}
- }
- }
-
- // Either right or both, left and right, are multiErrors. Rely on usual
- // expensive logic.
- errors := [2]error{left, right}
- return fromSlice(errors[0:])
-}
-
-// AppendInto appends an error into the destination of an error pointer and
-// returns whether the error being appended was non-nil.
-//
-// var err error
-// multierr.AppendInto(&err, r.Close())
-// multierr.AppendInto(&err, w.Close())
-//
-// The above is equivalent to,
-//
-// err := multierr.Append(r.Close(), w.Close())
-//
-// As AppendInto reports whether the provided error was non-nil, it may be
-// used to build a multierr error in a loop more ergonomically. For example:
-//
-// var err error
-// for line := range lines {
-// var item Item
-// if multierr.AppendInto(&err, parse(line, &item)) {
-// continue
-// }
-// items = append(items, item)
-// }
-//
-// Compare this with a version that relies solely on Append:
-//
-// var err error
-// for line := range lines {
-// var item Item
-// if parseErr := parse(line, &item); parseErr != nil {
-// err = multierr.Append(err, parseErr)
-// continue
-// }
-// items = append(items, item)
-// }
-func AppendInto(into *error, err error) (errored bool) {
- if into == nil {
- // We panic if 'into' is nil. This is not documented above
- // because suggesting that the pointer must be non-nil may
- // confuse users into thinking that the error that it points
- // to must be non-nil.
- panic("misuse of multierr.AppendInto: into pointer must not be nil")
- }
-
- if err == nil {
- return false
- }
- *into = Append(*into, err)
- return true
-}
-
-// Invoker is an operation that may fail with an error. Use it with
-// AppendInvoke to append the result of calling the function into an error.
-// This allows you to conveniently defer capture of failing operations.
-//
-// See also, Close and Invoke.
-type Invoker interface {
- Invoke() error
-}
-
-// Invoke wraps a function which may fail with an error to match the Invoker
-// interface. Use it to supply functions matching this signature to
-// AppendInvoke.
-//
-// For example,
-//
-// func processReader(r io.Reader) (err error) {
-// scanner := bufio.NewScanner(r)
-// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
-// for scanner.Scan() {
-// // ...
-// }
-// // ...
-// }
-//
-// In this example, the following line will construct the Invoker right away,
-// but defer the invocation of scanner.Err() until the function returns.
-//
-// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
-type Invoke func() error
-
-// Invoke calls the supplied function and returns its result.
-func (i Invoke) Invoke() error { return i() }
-
-// Close builds an Invoker that closes the provided io.Closer. Use it with
-// AppendInvoke to close io.Closers and append their results into an error.
-//
-// For example,
-//
-// func processFile(path string) (err error) {
-// f, err := os.Open(path)
-// if err != nil {
-// return err
-// }
-// defer multierr.AppendInvoke(&err, multierr.Close(f))
-// return processReader(f)
-// }
-//
-// In this example, multierr.Close will construct the Invoker right away, but
-// defer the invocation of f.Close until the function returns.
-//
-// defer multierr.AppendInvoke(&err, multierr.Close(f))
-func Close(closer io.Closer) Invoker {
- return Invoke(closer.Close)
-}
-
-// AppendInvoke appends the result of calling the given Invoker into the
-// provided error pointer. Use it with named returns to safely defer
-// invocation of fallible operations until a function returns, and capture the
-// resulting errors.
-//
-// func doSomething(...) (err error) {
-// // ...
-// f, err := openFile(..)
-// if err != nil {
-// return err
-// }
-//
-// // multierr will call f.Close() when this function returns and
-// // if the operation fails, its append its error into the
-// // returned error.
-// defer multierr.AppendInvoke(&err, multierr.Close(f))
-//
-// scanner := bufio.NewScanner(f)
-// // Similarly, this scheduled scanner.Err to be called and
-// // inspected when the function returns and append its error
-// // into the returned error.
-// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
-//
-// // ...
-// }
-//
-// Without defer, AppendInvoke behaves exactly like AppendInto.
-//
-// err := // ...
-// multierr.AppendInvoke(&err, mutltierr.Invoke(foo))
-//
-// // ...is roughly equivalent to...
-//
-// err := // ...
-// multierr.AppendInto(&err, foo())
-//
-// The advantage of the indirection introduced by Invoker is to make it easy
-// to defer the invocation of a function. Without this indirection, the
-// invoked function will be evaluated at the time of the defer block rather
-// than when the function returns.
-//
-// // BAD: This is likely not what the caller intended. This will evaluate
-// // foo() right away and append its result into the error when the
-// // function returns.
-// defer multierr.AppendInto(&err, foo())
-//
-// // GOOD: This will defer invocation of foo unutil the function returns.
-// defer multierr.AppendInvoke(&err, multierr.Invoke(foo))
-//
-// multierr provides a few Invoker implementations out of the box for
-// convenience. See Invoker for more information.
-func AppendInvoke(into *error, invoker Invoker) {
- AppendInto(into, invoker.Invoke())
-}
diff --git a/vendor/go.uber.org/multierr/glide.yaml b/vendor/go.uber.org/multierr/glide.yaml
deleted file mode 100644
index 6ef084ec24..0000000000
--- a/vendor/go.uber.org/multierr/glide.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-package: go.uber.org/multierr
-import:
-- package: go.uber.org/atomic
- version: ^1
-testImport:
-- package: github.com/stretchr/testify
- subpackages:
- - assert
diff --git a/vendor/go.uber.org/multierr/go.mod b/vendor/go.uber.org/multierr/go.mod
deleted file mode 100644
index 398d6c99e7..0000000000
--- a/vendor/go.uber.org/multierr/go.mod
+++ /dev/null
@@ -1,9 +0,0 @@
-module go.uber.org/multierr
-
-go 1.14
-
-require (
- github.com/stretchr/testify v1.7.0
- go.uber.org/atomic v1.7.0
- gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
-)
diff --git a/vendor/go.uber.org/multierr/go.sum b/vendor/go.uber.org/multierr/go.sum
deleted file mode 100644
index 75edd735e0..0000000000
--- a/vendor/go.uber.org/multierr/go.sum
+++ /dev/null
@@ -1,16 +0,0 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/vendor/go.uber.org/zap/.codecov.yml b/vendor/go.uber.org/zap/.codecov.yml
deleted file mode 100644
index 8e5ca7d3e2..0000000000
--- a/vendor/go.uber.org/zap/.codecov.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-coverage:
- range: 80..100
- round: down
- precision: 2
-
- status:
- project: # measuring the overall project coverage
- default: # context, you can create multiple ones with custom titles
- enabled: yes # must be yes|true to enable this status
- target: 95% # specify the target coverage for each commit status
- # option: "auto" (must increase from parent commit or pull request base)
- # option: "X%" a static target percentage to hit
- if_not_found: success # if parent is not found report status as success, error, or failure
- if_ci_failed: error # if ci fails report status as success, error, or failure
-ignore:
- - internal/readme/readme.go
-
diff --git a/vendor/go.uber.org/zap/.gitignore b/vendor/go.uber.org/zap/.gitignore
deleted file mode 100644
index da9d9d00b4..0000000000
--- a/vendor/go.uber.org/zap/.gitignore
+++ /dev/null
@@ -1,32 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-vendor
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
-*.prof
-*.pprof
-*.out
-*.log
-
-/bin
-cover.out
-cover.html
diff --git a/vendor/go.uber.org/zap/.readme.tmpl b/vendor/go.uber.org/zap/.readme.tmpl
deleted file mode 100644
index 3154a1e64c..0000000000
--- a/vendor/go.uber.org/zap/.readme.tmpl
+++ /dev/null
@@ -1,109 +0,0 @@
-# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
-
-Blazing fast, structured, leveled logging in Go.
-
-## Installation
-
-`go get -u go.uber.org/zap`
-
-Note that zap only supports the two most recent minor versions of Go.
-
-## Quick Start
-
-In contexts where performance is nice, but not critical, use the
-`SugaredLogger`. It's 4-10x faster than other structured logging
-packages and includes both structured and `printf`-style APIs.
-
-```go
-logger, _ := zap.NewProduction()
-defer logger.Sync() // flushes buffer, if any
-sugar := logger.Sugar()
-sugar.Infow("failed to fetch URL",
- // Structured context as loosely typed key-value pairs.
- "url", url,
- "attempt", 3,
- "backoff", time.Second,
-)
-sugar.Infof("Failed to fetch URL: %s", url)
-```
-
-When performance and type safety are critical, use the `Logger`. It's even
-faster than the `SugaredLogger` and allocates far less, but it only supports
-structured logging.
-
-```go
-logger, _ := zap.NewProduction()
-defer logger.Sync()
-logger.Info("failed to fetch URL",
- // Structured context as strongly typed Field values.
- zap.String("url", url),
- zap.Int("attempt", 3),
- zap.Duration("backoff", time.Second),
-)
-```
-
-See the [documentation][doc] and [FAQ](FAQ.md) for more details.
-
-## Performance
-
-For applications that log in the hot path, reflection-based serialization and
-string formatting are prohibitively expensive — they're CPU-intensive
-and make many small allocations. Put differently, using `encoding/json` and
-`fmt.Fprintf` to log tons of `interface{}`s makes your application slow.
-
-Zap takes a different approach. It includes a reflection-free, zero-allocation
-JSON encoder, and the base `Logger` strives to avoid serialization overhead
-and allocations wherever possible. By building the high-level `SugaredLogger`
-on that foundation, zap lets users *choose* when they need to count every
-allocation and when they'd prefer a more familiar, loosely typed API.
-
-As measured by its own [benchmarking suite][], not only is zap more performant
-than comparable structured logging packages — it's also faster than the
-standard library. Like all benchmarks, take these with a grain of salt.[1](#footnote-versions)
-
-Log a message and 10 fields:
-
-{{.BenchmarkAddingFields}}
-
-Log a message with a logger that already has 10 fields of context:
-
-{{.BenchmarkAccumulatedContext}}
-
-Log a static string, without any context or `printf`-style templating:
-
-{{.BenchmarkWithoutFields}}
-
-## Development Status: Stable
-
-All APIs are finalized, and no breaking changes will be made in the 1.x series
-of releases. Users of semver-aware dependency management systems should pin
-zap to `^1`.
-
-## Contributing
-
-We encourage and support an active, healthy community of contributors —
-including you! Details are in the [contribution guide](CONTRIBUTING.md) and
-the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on
-issues and pull requests, but you can also report any negative conduct to
-oss-conduct@uber.com. That email list is a private, safe space; even the zap
-maintainers don't have access, so don't hesitate to hold us to a high
-standard.
-
-
-
-Released under the [MIT License](LICENSE.txt).
-
- In particular, keep in mind that we may be
-benchmarking against slightly older versions of other packages. Versions are
-pinned in zap's [glide.lock][] file. [↩](#anchor-versions)
-
-[doc-img]: https://godoc.org/go.uber.org/zap?status.svg
-[doc]: https://godoc.org/go.uber.org/zap
-[ci-img]: https://travis-ci.com/uber-go/zap.svg?branch=master
-[ci]: https://travis-ci.com/uber-go/zap
-[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg
-[cov]: https://codecov.io/gh/uber-go/zap
-[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
-[glide.lock]: https://github.com/uber-go/zap/blob/master/glide.lock
-
diff --git a/vendor/go.uber.org/zap/CHANGELOG.md b/vendor/go.uber.org/zap/CHANGELOG.md
deleted file mode 100644
index 3b99bf0ac8..0000000000
--- a/vendor/go.uber.org/zap/CHANGELOG.md
+++ /dev/null
@@ -1,460 +0,0 @@
-# Changelog
-
-## 1.17.0 (25 May 2021)
-
-Bugfixes:
-* [#867][]: Encode `` for nil `error` instead of a panic.
-* [#931][], [#936][]: Update minimum version constraints to address
- vulnerabilities in dependencies.
-
-Enhancements:
-* [#865][]: Improve alignment of fields of the Logger struct, reducing its
- size from 96 to 80 bytes.
-* [#881][]: Support `grpclog.LoggerV2` in zapgrpc.
-* [#903][]: Support URL-encoded POST requests to the AtomicLevel HTTP handler
- with the `application/x-www-form-urlencoded` content type.
-* [#912][]: Support multi-field encoding with `zap.Inline`.
-* [#913][]: Speed up SugaredLogger for calls with a single string.
-* [#928][]: Add support for filtering by field name to `zaptest/observer`.
-
-Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release.
-
-## 1.16.0 (1 Sep 2020)
-
-Bugfixes:
-* [#828][]: Fix missing newline in IncreaseLevel error messages.
-* [#835][]: Fix panic in JSON encoder when encoding times or durations
- without specifying a time or duration encoder.
-* [#843][]: Honor CallerSkip when taking stack traces.
-* [#862][]: Fix the default file permissions to use `0666` and rely on the umask instead.
-* [#854][]: Encode `` for nil `Stringer` instead of a panic error log.
-
-Enhancements:
-* [#629][]: Added `zapcore.TimeEncoderOfLayout` to easily create time encoders
- for custom layouts.
-* [#697][]: Added support for a configurable delimiter in the console encoder.
-* [#852][]: Optimize console encoder by pooling the underlying JSON encoder.
-* [#844][]: Add ability to include the calling function as part of logs.
-* [#843][]: Add `StackSkip` for including truncated stacks as a field.
-* [#861][]: Add options to customize Fatal behaviour for better testability.
-
-Thanks to @SteelPhase, @tmshn, @lixingwang, @wyxloading, @moul, @segevfiner, @andy-retailnext and @jcorbin for their contributions to this release.
-
-## 1.15.0 (23 Apr 2020)
-
-Bugfixes:
-* [#804][]: Fix handling of `Time` values out of `UnixNano` range.
-* [#812][]: Fix `IncreaseLevel` being reset after a call to `With`.
-
-Enhancements:
-* [#806][]: Add `WithCaller` option to supersede the `AddCaller` option. This
- allows disabling annotation of log entries with caller information if
- previously enabled with `AddCaller`.
-* [#813][]: Deprecate `NewSampler` constructor in favor of
- `NewSamplerWithOptions` which supports a `SamplerHook` option. This option
- adds support for monitoring sampling decisions through a hook.
-
-Thanks to @danielbprice for their contributions to this release.
-
-## 1.14.1 (14 Mar 2020)
-
-Bugfixes:
-* [#791][]: Fix panic on attempting to build a logger with an invalid Config.
-* [#795][]: Vendoring Zap with `go mod vendor` no longer includes Zap's
- development-time dependencies.
-* [#799][]: Fix issue introduced in 1.14.0 that caused invalid JSON output to
- be generated for arrays of `time.Time` objects when using string-based time
- formats.
-
-Thanks to @YashishDua for their contributions to this release.
-
-## 1.14.0 (20 Feb 2020)
-
-Enhancements:
-* [#771][]: Optimize calls for disabled log levels.
-* [#773][]: Add millisecond duration encoder.
-* [#775][]: Add option to increase the level of a logger.
-* [#786][]: Optimize time formatters using `Time.AppendFormat` where possible.
-
-Thanks to @caibirdme for their contributions to this release.
-
-## 1.13.0 (13 Nov 2019)
-
-Enhancements:
-* [#758][]: Add `Intp`, `Stringp`, and other similar `*p` field constructors
- to log pointers to primitives with support for `nil` values.
-
-Thanks to @jbizzle for their contributions to this release.
-
-## 1.12.0 (29 Oct 2019)
-
-Enhancements:
-* [#751][]: Migrate to Go modules.
-
-## 1.11.0 (21 Oct 2019)
-
-Enhancements:
-* [#725][]: Add `zapcore.OmitKey` to omit keys in an `EncoderConfig`.
-* [#736][]: Add `RFC3339` and `RFC3339Nano` time encoders.
-
-Thanks to @juicemia, @uhthomas for their contributions to this release.
-
-## 1.10.0 (29 Apr 2019)
-
-Bugfixes:
-* [#657][]: Fix `MapObjectEncoder.AppendByteString` not adding value as a
- string.
-* [#706][]: Fix incorrect call depth to determine caller in Go 1.12.
-
-Enhancements:
-* [#610][]: Add `zaptest.WrapOptions` to wrap `zap.Option` for creating test
- loggers.
-* [#675][]: Don't panic when encoding a String field.
-* [#704][]: Disable HTML escaping for JSON objects encoded using the
- reflect-based encoder.
-
-Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions
-to this release.
-
-## v1.9.1 (06 Aug 2018)
-
-Bugfixes:
-
-* [#614][]: MapObjectEncoder should not ignore empty slices.
-
-## v1.9.0 (19 Jul 2018)
-
-Enhancements:
-* [#602][]: Reduce number of allocations when logging with reflection.
-* [#572][], [#606][]: Expose a registry for third-party logging sinks.
-
-Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and
-@dimroc for their contributions to this release.
-
-## v1.8.0 (13 Apr 2018)
-
-Enhancements:
-* [#508][]: Make log level configurable when redirecting the standard
- library's logger.
-* [#518][]: Add a logger that writes to a `*testing.TB`.
-* [#577][]: Add a top-level alias for `zapcore.Field` to clean up GoDoc.
-
-Bugfixes:
-* [#574][]: Add a missing import comment to `go.uber.org/zap/buffer`.
-
-Thanks to @DiSiqueira and @djui for their contributions to this release.
-
-## v1.7.1 (25 Sep 2017)
-
-Bugfixes:
-* [#504][]: Store strings when using AddByteString with the map encoder.
-
-## v1.7.0 (21 Sep 2017)
-
-Enhancements:
-
-* [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user
- to specify the level of the logged messages.
-
-## v1.6.0 (30 Aug 2017)
-
-Enhancements:
-
-* [#491][]: Omit zap stack frames from stacktraces.
-* [#490][]: Add a `ContextMap` method to observer logs for simpler
- field validation in tests.
-
-## v1.5.0 (22 Jul 2017)
-
-Enhancements:
-
-* [#460][] and [#470][]: Support errors produced by `go.uber.org/multierr`.
-* [#465][]: Support user-supplied encoders for logger names.
-
-Bugfixes:
-
-* [#477][]: Fix a bug that incorrectly truncated deep stacktraces.
-
-Thanks to @richard-tunein and @pavius for their contributions to this release.
-
-## v1.4.1 (08 Jun 2017)
-
-This release fixes two bugs.
-
-Bugfixes:
-
-* [#435][]: Support a variety of case conventions when unmarshaling levels.
-* [#444][]: Fix a panic in the observer.
-
-## v1.4.0 (12 May 2017)
-
-This release adds a few small features and is fully backward-compatible.
-
-Enhancements:
-
-* [#424][]: Add a `LineEnding` field to `EncoderConfig`, allowing users to
- override the Unix-style default.
-* [#425][]: Preserve time zones when logging times.
-* [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a
- variety of operations a bit simpler.
-
-## v1.3.0 (25 Apr 2017)
-
-This release adds an enhancement to zap's testing helpers as well as the
-ability to marshal an AtomicLevel. It is fully backward-compatible.
-
-Enhancements:
-
-* [#415][]: Add a substring-filtering helper to zap's observer. This is
- particularly useful when testing the `SugaredLogger`.
-* [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`.
-
-## v1.2.0 (13 Apr 2017)
-
-This release adds a gRPC compatibility wrapper. It is fully backward-compatible.
-
-Enhancements:
-
-* [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements
- `grpclog.Logger`.
-
-## v1.1.0 (31 Mar 2017)
-
-This release fixes two bugs and adds some enhancements to zap's testing helpers.
-It is fully backward-compatible.
-
-Bugfixes:
-
-* [#385][]: Fix caller path trimming on Windows.
-* [#396][]: Fix a panic when attempting to use non-existent directories with
- zap's configuration struct.
-
-Enhancements:
-
-* [#386][]: Add filtering helpers to zaptest's observing logger.
-
-Thanks to @moitias for contributing to this release.
-
-## v1.0.0 (14 Mar 2017)
-
-This is zap's first stable release. All exported APIs are now final, and no
-further breaking changes will be made in the 1.x release series. Anyone using a
-semver-aware dependency manager should now pin to `^1`.
-
-Breaking changes:
-
-* [#366][]: Add byte-oriented APIs to encoders to log UTF-8 encoded text without
- casting from `[]byte` to `string`.
-* [#364][]: To support buffering outputs, add `Sync` methods to `zapcore.Core`,
- `zap.Logger`, and `zap.SugaredLogger`.
-* [#371][]: Rename the `testutils` package to `zaptest`, which is less likely to
- clash with other testing helpers.
-
-Bugfixes:
-
-* [#362][]: Make the ISO8601 time formatters fixed-width, which is friendlier
- for tab-separated console output.
-* [#369][]: Remove the automatic locks in `zapcore.NewCore`, which allows zap to
- work with concurrency-safe `WriteSyncer` implementations.
-* [#347][]: Stop reporting errors when trying to `fsync` standard out on Linux
- systems.
-* [#373][]: Report the correct caller from zap's standard library
- interoperability wrappers.
-
-Enhancements:
-
-* [#348][]: Add a registry allowing third-party encodings to work with zap's
- built-in `Config`.
-* [#327][]: Make the representation of logger callers configurable (like times,
- levels, and durations).
-* [#376][]: Allow third-party encoders to use their own buffer pools, which
- removes the last performance advantage that zap's encoders have over plugins.
-* [#346][]: Add `CombineWriteSyncers`, a convenience function to tee multiple
- `WriteSyncer`s and lock the result.
-* [#365][]: Make zap's stacktraces compatible with mid-stack inlining (coming in
- Go 1.9).
-* [#372][]: Export zap's observing logger as `zaptest/observer`. This makes it
- easier for particularly punctilious users to unit test their application's
- logging.
-
-Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their
-contributions to this release.
-
-## v1.0.0-rc.3 (7 Mar 2017)
-
-This is the third release candidate for zap's stable release. There are no
-breaking changes.
-
-Bugfixes:
-
-* [#339][]: Byte slices passed to `zap.Any` are now correctly treated as binary blobs
- rather than `[]uint8`.
-
-Enhancements:
-
-* [#307][]: Users can opt into colored output for log levels.
-* [#353][]: In addition to hijacking the output of the standard library's
- package-global logging functions, users can now construct a zap-backed
- `log.Logger` instance.
-* [#311][]: Frames from common runtime functions and some of zap's internal
- machinery are now omitted from stacktraces.
-
-Thanks to @ansel1 and @suyash for their contributions to this release.
-
-## v1.0.0-rc.2 (21 Feb 2017)
-
-This is the second release candidate for zap's stable release. It includes two
-breaking changes.
-
-Breaking changes:
-
-* [#316][]: Zap's global loggers are now fully concurrency-safe
- (previously, users had to ensure that `ReplaceGlobals` was called before the
- loggers were in use). However, they must now be accessed via the `L()` and
- `S()` functions. Users can update their projects with
-
- ```
- gofmt -r "zap.L -> zap.L()" -w .
- gofmt -r "zap.S -> zap.S()" -w .
- ```
-* [#309][] and [#317][]: RC1 was mistakenly shipped with invalid
- JSON and YAML struct tags on all config structs. This release fixes the tags
- and adds static analysis to prevent similar bugs in the future.
-
-Bugfixes:
-
-* [#321][]: Redirecting the standard library's `log` output now
- correctly reports the logger's caller.
-
-Enhancements:
-
-* [#325][] and [#333][]: Zap now transparently supports non-standard, rich
- errors like those produced by `github.com/pkg/errors`.
-* [#326][]: Though `New(nil)` continues to return a no-op logger, `NewNop()` is
- now preferred. Users can update their projects with `gofmt -r 'zap.New(nil) ->
- zap.NewNop()' -w .`.
-* [#300][]: Incorrectly importing zap as `github.com/uber-go/zap` now returns a
- more informative error.
-
-Thanks to @skipor and @chapsuk for their contributions to this release.
-
-## v1.0.0-rc.1 (14 Feb 2017)
-
-This is the first release candidate for zap's stable release. There are multiple
-breaking changes and improvements from the pre-release version. Most notably:
-
-* **Zap's import path is now "go.uber.org/zap"** — all users will
- need to update their code.
-* User-facing types and functions remain in the `zap` package. Code relevant
- largely to extension authors is now in the `zapcore` package.
-* The `zapcore.Core` type makes it easy for third-party packages to use zap's
- internals but provide a different user-facing API.
-* `Logger` is now a concrete type instead of an interface.
-* A less verbose (though slower) logging API is included by default.
-* Package-global loggers `L` and `S` are included.
-* A human-friendly console encoder is included.
-* A declarative config struct allows common logger configurations to be managed
- as configuration instead of code.
-* Sampling is more accurate, and doesn't depend on the standard library's shared
- timer heap.
-
-## v0.1.0-beta.1 (6 Feb 2017)
-
-This is a minor version, tagged to allow users to pin to the pre-1.0 APIs and
-upgrade at their leisure. Since this is the first tagged release, there are no
-backward compatibility concerns and all functionality is new.
-
-Early zap adopters should pin to the 0.1.x minor version until they're ready to
-upgrade to the upcoming stable release.
-
-[#316]: https://github.com/uber-go/zap/pull/316
-[#309]: https://github.com/uber-go/zap/pull/309
-[#317]: https://github.com/uber-go/zap/pull/317
-[#321]: https://github.com/uber-go/zap/pull/321
-[#325]: https://github.com/uber-go/zap/pull/325
-[#333]: https://github.com/uber-go/zap/pull/333
-[#326]: https://github.com/uber-go/zap/pull/326
-[#300]: https://github.com/uber-go/zap/pull/300
-[#339]: https://github.com/uber-go/zap/pull/339
-[#307]: https://github.com/uber-go/zap/pull/307
-[#353]: https://github.com/uber-go/zap/pull/353
-[#311]: https://github.com/uber-go/zap/pull/311
-[#366]: https://github.com/uber-go/zap/pull/366
-[#364]: https://github.com/uber-go/zap/pull/364
-[#371]: https://github.com/uber-go/zap/pull/371
-[#362]: https://github.com/uber-go/zap/pull/362
-[#369]: https://github.com/uber-go/zap/pull/369
-[#347]: https://github.com/uber-go/zap/pull/347
-[#373]: https://github.com/uber-go/zap/pull/373
-[#348]: https://github.com/uber-go/zap/pull/348
-[#327]: https://github.com/uber-go/zap/pull/327
-[#376]: https://github.com/uber-go/zap/pull/376
-[#346]: https://github.com/uber-go/zap/pull/346
-[#365]: https://github.com/uber-go/zap/pull/365
-[#372]: https://github.com/uber-go/zap/pull/372
-[#385]: https://github.com/uber-go/zap/pull/385
-[#396]: https://github.com/uber-go/zap/pull/396
-[#386]: https://github.com/uber-go/zap/pull/386
-[#402]: https://github.com/uber-go/zap/pull/402
-[#415]: https://github.com/uber-go/zap/pull/415
-[#416]: https://github.com/uber-go/zap/pull/416
-[#424]: https://github.com/uber-go/zap/pull/424
-[#425]: https://github.com/uber-go/zap/pull/425
-[#431]: https://github.com/uber-go/zap/pull/431
-[#435]: https://github.com/uber-go/zap/pull/435
-[#444]: https://github.com/uber-go/zap/pull/444
-[#477]: https://github.com/uber-go/zap/pull/477
-[#465]: https://github.com/uber-go/zap/pull/465
-[#460]: https://github.com/uber-go/zap/pull/460
-[#470]: https://github.com/uber-go/zap/pull/470
-[#487]: https://github.com/uber-go/zap/pull/487
-[#490]: https://github.com/uber-go/zap/pull/490
-[#491]: https://github.com/uber-go/zap/pull/491
-[#504]: https://github.com/uber-go/zap/pull/504
-[#508]: https://github.com/uber-go/zap/pull/508
-[#518]: https://github.com/uber-go/zap/pull/518
-[#577]: https://github.com/uber-go/zap/pull/577
-[#574]: https://github.com/uber-go/zap/pull/574
-[#602]: https://github.com/uber-go/zap/pull/602
-[#572]: https://github.com/uber-go/zap/pull/572
-[#606]: https://github.com/uber-go/zap/pull/606
-[#614]: https://github.com/uber-go/zap/pull/614
-[#657]: https://github.com/uber-go/zap/pull/657
-[#706]: https://github.com/uber-go/zap/pull/706
-[#610]: https://github.com/uber-go/zap/pull/610
-[#675]: https://github.com/uber-go/zap/pull/675
-[#704]: https://github.com/uber-go/zap/pull/704
-[#725]: https://github.com/uber-go/zap/pull/725
-[#736]: https://github.com/uber-go/zap/pull/736
-[#751]: https://github.com/uber-go/zap/pull/751
-[#758]: https://github.com/uber-go/zap/pull/758
-[#771]: https://github.com/uber-go/zap/pull/771
-[#773]: https://github.com/uber-go/zap/pull/773
-[#775]: https://github.com/uber-go/zap/pull/775
-[#786]: https://github.com/uber-go/zap/pull/786
-[#791]: https://github.com/uber-go/zap/pull/791
-[#795]: https://github.com/uber-go/zap/pull/795
-[#799]: https://github.com/uber-go/zap/pull/799
-[#804]: https://github.com/uber-go/zap/pull/804
-[#812]: https://github.com/uber-go/zap/pull/812
-[#806]: https://github.com/uber-go/zap/pull/806
-[#813]: https://github.com/uber-go/zap/pull/813
-[#629]: https://github.com/uber-go/zap/pull/629
-[#697]: https://github.com/uber-go/zap/pull/697
-[#828]: https://github.com/uber-go/zap/pull/828
-[#835]: https://github.com/uber-go/zap/pull/835
-[#843]: https://github.com/uber-go/zap/pull/843
-[#844]: https://github.com/uber-go/zap/pull/844
-[#852]: https://github.com/uber-go/zap/pull/852
-[#854]: https://github.com/uber-go/zap/pull/854
-[#861]: https://github.com/uber-go/zap/pull/861
-[#862]: https://github.com/uber-go/zap/pull/862
-[#865]: https://github.com/uber-go/zap/pull/865
-[#867]: https://github.com/uber-go/zap/pull/867
-[#881]: https://github.com/uber-go/zap/pull/881
-[#903]: https://github.com/uber-go/zap/pull/903
-[#912]: https://github.com/uber-go/zap/pull/912
-[#913]: https://github.com/uber-go/zap/pull/913
-[#928]: https://github.com/uber-go/zap/pull/928
-[#931]: https://github.com/uber-go/zap/pull/931
-[#936]: https://github.com/uber-go/zap/pull/936
diff --git a/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md b/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
deleted file mode 100644
index e327d9aa5c..0000000000
--- a/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# Contributor Covenant Code of Conduct
-
-## Our Pledge
-
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age,
-body size, disability, ethnicity, gender identity and expression, level of
-experience, nationality, personal appearance, race, religion, or sexual
-identity and orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery and unwelcome sexual attention or
- advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
-
-## Scope
-
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an
-appointed representative at an online or offline event. Representation of a
-project may be further defined and clarified by project maintainers.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at oss-conduct@uber.com. The project
-team will review and investigate all complaints, and will respond in a way
-that it deems appropriate to the circumstances. The project team is obligated
-to maintain confidentiality with regard to the reporter of an incident.
-Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
-
-## Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage],
-version 1.4, available at
-[http://contributor-covenant.org/version/1/4][version].
-
-[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/go.uber.org/zap/CONTRIBUTING.md b/vendor/go.uber.org/zap/CONTRIBUTING.md
deleted file mode 100644
index 5cd9656871..0000000000
--- a/vendor/go.uber.org/zap/CONTRIBUTING.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# Contributing
-
-We'd love your help making zap the very best structured logging library in Go!
-
-If you'd like to add new exported APIs, please [open an issue][open-issue]
-describing your proposal — discussing API changes ahead of time makes
-pull request review much smoother. In your issue, pull request, and any other
-communications, please remember to treat your fellow contributors with
-respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously.
-
-Note that you'll need to sign [Uber's Contributor License Agreement][cla]
-before we can accept any of your contributions. If necessary, a bot will remind
-you to accept the CLA when you open your pull request.
-
-## Setup
-
-[Fork][fork], then clone the repository:
-
-```
-mkdir -p $GOPATH/src/go.uber.org
-cd $GOPATH/src/go.uber.org
-git clone git@github.com:your_github_username/zap.git
-cd zap
-git remote add upstream https://github.com/uber-go/zap.git
-git fetch upstream
-```
-
-Make sure that the tests and the linters pass:
-
-```
-make test
-make lint
-```
-
-If you're not using the minor version of Go specified in the Makefile's
-`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is
-fine, but it means that you'll only discover lint failures after you open your
-pull request.
-
-## Making Changes
-
-Start by creating a new branch for your changes:
-
-```
-cd $GOPATH/src/go.uber.org/zap
-git checkout master
-git fetch upstream
-git rebase upstream/master
-git checkout -b cool_new_feature
-```
-
-Make your changes, then ensure that `make lint` and `make test` still pass. If
-you're satisfied with your changes, push them to your fork.
-
-```
-git push origin cool_new_feature
-```
-
-Then use the GitHub UI to open a pull request.
-
-At this point, you're waiting on us to review your changes. We *try* to respond
-to issues and pull requests within a few business days, and we may suggest some
-improvements or alternatives. Once your changes are approved, one of the
-project maintainers will merge them.
-
-We're much more likely to approve your changes if you:
-
-* Add tests for new functionality.
-* Write a [good commit message][commit-message].
-* Maintain backward compatibility.
-
-[fork]: https://github.com/uber-go/zap/fork
-[open-issue]: https://github.com/uber-go/zap/issues/new
-[cla]: https://cla-assistant.io/uber-go/zap
-[commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
diff --git a/vendor/go.uber.org/zap/FAQ.md b/vendor/go.uber.org/zap/FAQ.md
deleted file mode 100644
index b183b20bc1..0000000000
--- a/vendor/go.uber.org/zap/FAQ.md
+++ /dev/null
@@ -1,164 +0,0 @@
-# Frequently Asked Questions
-
-## Design
-
-### Why spend so much effort on logger performance?
-
-Of course, most applications won't notice the impact of a slow logger: they
-already take tens or hundreds of milliseconds for each operation, so an extra
-millisecond doesn't matter.
-
-On the other hand, why *not* make structured logging fast? The `SugaredLogger`
-isn't any harder to use than other logging packages, and the `Logger` makes
-structured logging possible in performance-sensitive contexts. Across a fleet
-of Go microservices, making each application even slightly more efficient adds
-up quickly.
-
-### Why aren't `Logger` and `SugaredLogger` interfaces?
-
-Unlike the familiar `io.Writer` and `http.Handler`, `Logger` and
-`SugaredLogger` interfaces would include *many* methods. As [Rob Pike points
-out][go-proverbs], "The bigger the interface, the weaker the abstraction."
-Interfaces are also rigid — *any* change requires releasing a new major
-version, since it breaks all third-party implementations.
-
-Making the `Logger` and `SugaredLogger` concrete types doesn't sacrifice much
-abstraction, and it lets us add methods without introducing breaking changes.
-Your applications should define and depend upon an interface that includes
-just the methods you use.
-
-### Why are some of my logs missing?
-
-Logs are dropped intentionally by zap when sampling is enabled. The production
-configuration (as returned by `NewProductionConfig()` enables sampling which will
-cause repeated logs within a second to be sampled. See more details on why sampling
-is enabled in [Why sample application logs](https://github.com/uber-go/zap/blob/master/FAQ.md#why-sample-application-logs).
-
-### Why sample application logs?
-
-Applications often experience runs of errors, either because of a bug or
-because of a misbehaving user. Logging errors is usually a good idea, but it
-can easily make this bad situation worse: not only is your application coping
-with a flood of errors, it's also spending extra CPU cycles and I/O logging
-those errors. Since writes are typically serialized, logging limits throughput
-when you need it most.
-
-Sampling fixes this problem by dropping repetitive log entries. Under normal
-conditions, your application writes out every entry. When similar entries are
-logged hundreds or thousands of times each second, though, zap begins dropping
-duplicates to preserve throughput.
-
-### Why do the structured logging APIs take a message in addition to fields?
-
-Subjectively, we find it helpful to accompany structured context with a brief
-description. This isn't critical during development, but it makes debugging
-and operating unfamiliar systems much easier.
-
-More concretely, zap's sampling algorithm uses the message to identify
-duplicate entries. In our experience, this is a practical middle ground
-between random sampling (which often drops the exact entry that you need while
-debugging) and hashing the complete entry (which is prohibitively expensive).
-
-### Why include package-global loggers?
-
-Since so many other logging packages include a global logger, many
-applications aren't designed to accept loggers as explicit parameters.
-Changing function signatures is often a breaking change, so zap includes
-global loggers to simplify migration.
-
-Avoid them where possible.
-
-### Why include dedicated Panic and Fatal log levels?
-
-In general, application code should handle errors gracefully instead of using
-`panic` or `os.Exit`. However, every rule has exceptions, and it's common to
-crash when an error is truly unrecoverable. To avoid losing any information
-— especially the reason for the crash — the logger must flush any
-buffered entries before the process exits.
-
-Zap makes this easy by offering `Panic` and `Fatal` logging methods that
-automatically flush before exiting. Of course, this doesn't guarantee that
-logs will never be lost, but it eliminates a common error.
-
-See the discussion in uber-go/zap#207 for more details.
-
-### What's `DPanic`?
-
-`DPanic` stands for "panic in development." In development, it logs at
-`PanicLevel`; otherwise, it logs at `ErrorLevel`. `DPanic` makes it easier to
-catch errors that are theoretically possible, but shouldn't actually happen,
-*without* crashing in production.
-
-If you've ever written code like this, you need `DPanic`:
-
-```go
-if err != nil {
- panic(fmt.Sprintf("shouldn't ever get here: %v", err))
-}
-```
-
-## Installation
-
-### What does the error `expects import "go.uber.org/zap"` mean?
-
-Either zap was installed incorrectly or you're referencing the wrong package
-name in your code.
-
-Zap's source code happens to be hosted on GitHub, but the [import
-path][import-path] is `go.uber.org/zap`. This gives us, the project
-maintainers, the freedom to move the source code if necessary. However, it
-means that you need to take a little care when installing and using the
-package.
-
-If you follow two simple rules, everything should work: install zap with `go
-get -u go.uber.org/zap`, and always import it in your code with `import
-"go.uber.org/zap"`. Your code shouldn't contain *any* references to
-`github.com/uber-go/zap`.
-
-## Usage
-
-### Does zap support log rotation?
-
-Zap doesn't natively support rotating log files, since we prefer to leave this
-to an external program like `logrotate`.
-
-However, it's easy to integrate a log rotation package like
-[`gopkg.in/natefinch/lumberjack.v2`][lumberjack] as a `zapcore.WriteSyncer`.
-
-```go
-// lumberjack.Logger is already safe for concurrent use, so we don't need to
-// lock it.
-w := zapcore.AddSync(&lumberjack.Logger{
- Filename: "/var/log/myapp/foo.log",
- MaxSize: 500, // megabytes
- MaxBackups: 3,
- MaxAge: 28, // days
-})
-core := zapcore.NewCore(
- zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
- w,
- zap.InfoLevel,
-)
-logger := zap.New(core)
-```
-
-## Extensions
-
-We'd love to support every logging need within zap itself, but we're only
-familiar with a handful of log ingestion systems, flag-parsing packages, and
-the like. Rather than merging code that we can't effectively debug and
-support, we'd rather grow an ecosystem of zap extensions.
-
-We're aware of the following extensions, but haven't used them ourselves:
-
-| Package | Integration |
-| --- | --- |
-| `github.com/tchap/zapext` | Sentry, syslog |
-| `github.com/fgrosse/zaptest` | Ginkgo |
-| `github.com/blendle/zapdriver` | Stackdriver |
-| `github.com/moul/zapgorm` | Gorm |
-| `github.com/moul/zapfilter` | Advanced filtering rules |
-
-[go-proverbs]: https://go-proverbs.github.io/
-[import-path]: https://golang.org/cmd/go/#hdr-Remote_import_paths
-[lumberjack]: https://godoc.org/gopkg.in/natefinch/lumberjack.v2
diff --git a/vendor/go.uber.org/zap/LICENSE.txt b/vendor/go.uber.org/zap/LICENSE.txt
deleted file mode 100644
index 6652bed45f..0000000000
--- a/vendor/go.uber.org/zap/LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2016-2017 Uber Technologies, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/vendor/go.uber.org/zap/Makefile b/vendor/go.uber.org/zap/Makefile
deleted file mode 100644
index 9b1bc3b0e1..0000000000
--- a/vendor/go.uber.org/zap/Makefile
+++ /dev/null
@@ -1,73 +0,0 @@
-export GOBIN ?= $(shell pwd)/bin
-
-GOLINT = $(GOBIN)/golint
-STATICCHECK = $(GOBIN)/staticcheck
-BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
-
-# Directories containing independent Go modules.
-#
-# We track coverage only for the main module.
-MODULE_DIRS = . ./benchmarks ./zapgrpc/internal/test
-
-# Many Go tools take file globs or directories as arguments instead of packages.
-GO_FILES := $(shell \
- find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
- -o -name '*.go' -print | cut -b3-)
-
-.PHONY: all
-all: lint test
-
-.PHONY: lint
-lint: $(GOLINT) $(STATICCHECK)
- @rm -rf lint.log
- @echo "Checking formatting..."
- @gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
- @echo "Checking vet..."
- @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log
- @echo "Checking lint..."
- @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(GOLINT) ./... 2>&1) &&) true | tee -a lint.log
- @echo "Checking staticcheck..."
- @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log
- @echo "Checking for unresolved FIXMEs..."
- @git grep -i fixme | grep -v -e Makefile | tee -a lint.log
- @echo "Checking for license headers..."
- @./checklicense.sh | tee -a lint.log
- @[ ! -s lint.log ]
- @echo "Checking 'go mod tidy'..."
- @make tidy
- @if ! git diff --quiet; then \
- echo "'go mod tidy' resulted in changes or working tree is dirty:"; \
- git --no-pager diff; \
- fi
-
-$(GOLINT):
- cd tools && go install golang.org/x/lint/golint
-
-$(STATICCHECK):
- cd tools && go install honnef.co/go/tools/cmd/staticcheck
-
-.PHONY: test
-test:
- @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go test -race ./...) &&) true
-
-.PHONY: cover
-cover:
- go test -race -coverprofile=cover.out -coverpkg=./... ./...
- go tool cover -html=cover.out -o cover.html
-
-.PHONY: bench
-BENCH ?= .
-bench:
- @$(foreach dir,$(MODULE_DIRS), ( \
- cd $(dir) && \
- go list ./... | xargs -n1 go test -bench=$(BENCH) -run="^$$" $(BENCH_FLAGS) \
- ) &&) true
-
-.PHONY: updatereadme
-updatereadme:
- rm -f README.md
- cat .readme.tmpl | go run internal/readme/readme.go > README.md
-
-.PHONY: tidy
-tidy:
- @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true
diff --git a/vendor/go.uber.org/zap/README.md b/vendor/go.uber.org/zap/README.md
deleted file mode 100644
index 1e64d6cffc..0000000000
--- a/vendor/go.uber.org/zap/README.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
-
-Blazing fast, structured, leveled logging in Go.
-
-## Installation
-
-`go get -u go.uber.org/zap`
-
-Note that zap only supports the two most recent minor versions of Go.
-
-## Quick Start
-
-In contexts where performance is nice, but not critical, use the
-`SugaredLogger`. It's 4-10x faster than other structured logging
-packages and includes both structured and `printf`-style APIs.
-
-```go
-logger, _ := zap.NewProduction()
-defer logger.Sync() // flushes buffer, if any
-sugar := logger.Sugar()
-sugar.Infow("failed to fetch URL",
- // Structured context as loosely typed key-value pairs.
- "url", url,
- "attempt", 3,
- "backoff", time.Second,
-)
-sugar.Infof("Failed to fetch URL: %s", url)
-```
-
-When performance and type safety are critical, use the `Logger`. It's even
-faster than the `SugaredLogger` and allocates far less, but it only supports
-structured logging.
-
-```go
-logger, _ := zap.NewProduction()
-defer logger.Sync()
-logger.Info("failed to fetch URL",
- // Structured context as strongly typed Field values.
- zap.String("url", url),
- zap.Int("attempt", 3),
- zap.Duration("backoff", time.Second),
-)
-```
-
-See the [documentation][doc] and [FAQ](FAQ.md) for more details.
-
-## Performance
-
-For applications that log in the hot path, reflection-based serialization and
-string formatting are prohibitively expensive — they're CPU-intensive
-and make many small allocations. Put differently, using `encoding/json` and
-`fmt.Fprintf` to log tons of `interface{}`s makes your application slow.
-
-Zap takes a different approach. It includes a reflection-free, zero-allocation
-JSON encoder, and the base `Logger` strives to avoid serialization overhead
-and allocations wherever possible. By building the high-level `SugaredLogger`
-on that foundation, zap lets users *choose* when they need to count every
-allocation and when they'd prefer a more familiar, loosely typed API.
-
-As measured by its own [benchmarking suite][], not only is zap more performant
-than comparable structured logging packages — it's also faster than the
-standard library. Like all benchmarks, take these with a grain of salt.[1](#footnote-versions)
-
-Log a message and 10 fields:
-
-| Package | Time | Time % to zap | Objects Allocated |
-| :------ | :--: | :-----------: | :---------------: |
-| :zap: zap | 862 ns/op | +0% | 5 allocs/op
-| :zap: zap (sugared) | 1250 ns/op | +45% | 11 allocs/op
-| zerolog | 4021 ns/op | +366% | 76 allocs/op
-| go-kit | 4542 ns/op | +427% | 105 allocs/op
-| apex/log | 26785 ns/op | +3007% | 115 allocs/op
-| logrus | 29501 ns/op | +3322% | 125 allocs/op
-| log15 | 29906 ns/op | +3369% | 122 allocs/op
-
-Log a message with a logger that already has 10 fields of context:
-
-| Package | Time | Time % to zap | Objects Allocated |
-| :------ | :--: | :-----------: | :---------------: |
-| :zap: zap | 126 ns/op | +0% | 0 allocs/op
-| :zap: zap (sugared) | 187 ns/op | +48% | 2 allocs/op
-| zerolog | 88 ns/op | -30% | 0 allocs/op
-| go-kit | 5087 ns/op | +3937% | 103 allocs/op
-| log15 | 18548 ns/op | +14621% | 73 allocs/op
-| apex/log | 26012 ns/op | +20544% | 104 allocs/op
-| logrus | 27236 ns/op | +21516% | 113 allocs/op
-
-Log a static string, without any context or `printf`-style templating:
-
-| Package | Time | Time % to zap | Objects Allocated |
-| :------ | :--: | :-----------: | :---------------: |
-| :zap: zap | 118 ns/op | +0% | 0 allocs/op
-| :zap: zap (sugared) | 191 ns/op | +62% | 2 allocs/op
-| zerolog | 93 ns/op | -21% | 0 allocs/op
-| go-kit | 280 ns/op | +137% | 11 allocs/op
-| standard library | 499 ns/op | +323% | 2 allocs/op
-| apex/log | 1990 ns/op | +1586% | 10 allocs/op
-| logrus | 3129 ns/op | +2552% | 24 allocs/op
-| log15 | 3887 ns/op | +3194% | 23 allocs/op
-
-## Development Status: Stable
-
-All APIs are finalized, and no breaking changes will be made in the 1.x series
-of releases. Users of semver-aware dependency management systems should pin
-zap to `^1`.
-
-## Contributing
-
-We encourage and support an active, healthy community of contributors —
-including you! Details are in the [contribution guide](CONTRIBUTING.md) and
-the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on
-issues and pull requests, but you can also report any negative conduct to
-oss-conduct@uber.com. That email list is a private, safe space; even the zap
-maintainers don't have access, so don't hesitate to hold us to a high
-standard.
-
-
-
-Released under the [MIT License](LICENSE.txt).
-
- In particular, keep in mind that we may be
-benchmarking against slightly older versions of other packages. Versions are
-pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions)
-
-[doc-img]: https://pkg.go.dev/badge/go.uber.org/zap
-[doc]: https://pkg.go.dev/go.uber.org/zap
-[ci-img]: https://github.com/uber-go/zap/actions/workflows/go.yml/badge.svg
-[ci]: https://github.com/uber-go/zap/actions/workflows/go.yml
-[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg
-[cov]: https://codecov.io/gh/uber-go/zap
-[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
-[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod
-
diff --git a/vendor/go.uber.org/zap/array.go b/vendor/go.uber.org/zap/array.go
deleted file mode 100644
index 5be3704a3e..0000000000
--- a/vendor/go.uber.org/zap/array.go
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "time"
-
- "go.uber.org/zap/zapcore"
-)
-
-// Array constructs a field with the given key and ArrayMarshaler. It provides
-// a flexible, but still type-safe and efficient, way to add array-like types
-// to the logging context. The struct's MarshalLogArray method is called lazily.
-func Array(key string, val zapcore.ArrayMarshaler) Field {
- return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val}
-}
-
-// Bools constructs a field that carries a slice of bools.
-func Bools(key string, bs []bool) Field {
- return Array(key, bools(bs))
-}
-
-// ByteStrings constructs a field that carries a slice of []byte, each of which
-// must be UTF-8 encoded text.
-func ByteStrings(key string, bss [][]byte) Field {
- return Array(key, byteStringsArray(bss))
-}
-
-// Complex128s constructs a field that carries a slice of complex numbers.
-func Complex128s(key string, nums []complex128) Field {
- return Array(key, complex128s(nums))
-}
-
-// Complex64s constructs a field that carries a slice of complex numbers.
-func Complex64s(key string, nums []complex64) Field {
- return Array(key, complex64s(nums))
-}
-
-// Durations constructs a field that carries a slice of time.Durations.
-func Durations(key string, ds []time.Duration) Field {
- return Array(key, durations(ds))
-}
-
-// Float64s constructs a field that carries a slice of floats.
-func Float64s(key string, nums []float64) Field {
- return Array(key, float64s(nums))
-}
-
-// Float32s constructs a field that carries a slice of floats.
-func Float32s(key string, nums []float32) Field {
- return Array(key, float32s(nums))
-}
-
-// Ints constructs a field that carries a slice of integers.
-func Ints(key string, nums []int) Field {
- return Array(key, ints(nums))
-}
-
-// Int64s constructs a field that carries a slice of integers.
-func Int64s(key string, nums []int64) Field {
- return Array(key, int64s(nums))
-}
-
-// Int32s constructs a field that carries a slice of integers.
-func Int32s(key string, nums []int32) Field {
- return Array(key, int32s(nums))
-}
-
-// Int16s constructs a field that carries a slice of integers.
-func Int16s(key string, nums []int16) Field {
- return Array(key, int16s(nums))
-}
-
-// Int8s constructs a field that carries a slice of integers.
-func Int8s(key string, nums []int8) Field {
- return Array(key, int8s(nums))
-}
-
-// Strings constructs a field that carries a slice of strings.
-func Strings(key string, ss []string) Field {
- return Array(key, stringArray(ss))
-}
-
-// Times constructs a field that carries a slice of time.Times.
-func Times(key string, ts []time.Time) Field {
- return Array(key, times(ts))
-}
-
-// Uints constructs a field that carries a slice of unsigned integers.
-func Uints(key string, nums []uint) Field {
- return Array(key, uints(nums))
-}
-
-// Uint64s constructs a field that carries a slice of unsigned integers.
-func Uint64s(key string, nums []uint64) Field {
- return Array(key, uint64s(nums))
-}
-
-// Uint32s constructs a field that carries a slice of unsigned integers.
-func Uint32s(key string, nums []uint32) Field {
- return Array(key, uint32s(nums))
-}
-
-// Uint16s constructs a field that carries a slice of unsigned integers.
-func Uint16s(key string, nums []uint16) Field {
- return Array(key, uint16s(nums))
-}
-
-// Uint8s constructs a field that carries a slice of unsigned integers.
-func Uint8s(key string, nums []uint8) Field {
- return Array(key, uint8s(nums))
-}
-
-// Uintptrs constructs a field that carries a slice of pointer addresses.
-func Uintptrs(key string, us []uintptr) Field {
- return Array(key, uintptrs(us))
-}
-
-// Errors constructs a field that carries a slice of errors.
-func Errors(key string, errs []error) Field {
- return Array(key, errArray(errs))
-}
-
-type bools []bool
-
-func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range bs {
- arr.AppendBool(bs[i])
- }
- return nil
-}
-
-type byteStringsArray [][]byte
-
-func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range bss {
- arr.AppendByteString(bss[i])
- }
- return nil
-}
-
-type complex128s []complex128
-
-func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendComplex128(nums[i])
- }
- return nil
-}
-
-type complex64s []complex64
-
-func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendComplex64(nums[i])
- }
- return nil
-}
-
-type durations []time.Duration
-
-func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range ds {
- arr.AppendDuration(ds[i])
- }
- return nil
-}
-
-type float64s []float64
-
-func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendFloat64(nums[i])
- }
- return nil
-}
-
-type float32s []float32
-
-func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendFloat32(nums[i])
- }
- return nil
-}
-
-type ints []int
-
-func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendInt(nums[i])
- }
- return nil
-}
-
-type int64s []int64
-
-func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendInt64(nums[i])
- }
- return nil
-}
-
-type int32s []int32
-
-func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendInt32(nums[i])
- }
- return nil
-}
-
-type int16s []int16
-
-func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendInt16(nums[i])
- }
- return nil
-}
-
-type int8s []int8
-
-func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendInt8(nums[i])
- }
- return nil
-}
-
-type stringArray []string
-
-func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range ss {
- arr.AppendString(ss[i])
- }
- return nil
-}
-
-type times []time.Time
-
-func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range ts {
- arr.AppendTime(ts[i])
- }
- return nil
-}
-
-type uints []uint
-
-func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendUint(nums[i])
- }
- return nil
-}
-
-type uint64s []uint64
-
-func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendUint64(nums[i])
- }
- return nil
-}
-
-type uint32s []uint32
-
-func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendUint32(nums[i])
- }
- return nil
-}
-
-type uint16s []uint16
-
-func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendUint16(nums[i])
- }
- return nil
-}
-
-type uint8s []uint8
-
-func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendUint8(nums[i])
- }
- return nil
-}
-
-type uintptrs []uintptr
-
-func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range nums {
- arr.AppendUintptr(nums[i])
- }
- return nil
-}
diff --git a/vendor/go.uber.org/zap/buffer/buffer.go b/vendor/go.uber.org/zap/buffer/buffer.go
deleted file mode 100644
index 3f4b86e081..0000000000
--- a/vendor/go.uber.org/zap/buffer/buffer.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package buffer provides a thin wrapper around a byte slice. Unlike the
-// standard library's bytes.Buffer, it supports a portion of the strconv
-// package's zero-allocation formatters.
-package buffer // import "go.uber.org/zap/buffer"
-
-import (
- "strconv"
- "time"
-)
-
-const _size = 1024 // by default, create 1 KiB buffers
-
-// Buffer is a thin wrapper around a byte slice. It's intended to be pooled, so
-// the only way to construct one is via a Pool.
-type Buffer struct {
- bs []byte
- pool Pool
-}
-
-// AppendByte writes a single byte to the Buffer.
-func (b *Buffer) AppendByte(v byte) {
- b.bs = append(b.bs, v)
-}
-
-// AppendString writes a string to the Buffer.
-func (b *Buffer) AppendString(s string) {
- b.bs = append(b.bs, s...)
-}
-
-// AppendInt appends an integer to the underlying buffer (assuming base 10).
-func (b *Buffer) AppendInt(i int64) {
- b.bs = strconv.AppendInt(b.bs, i, 10)
-}
-
-// AppendTime appends the time formatted using the specified layout.
-func (b *Buffer) AppendTime(t time.Time, layout string) {
- b.bs = t.AppendFormat(b.bs, layout)
-}
-
-// AppendUint appends an unsigned integer to the underlying buffer (assuming
-// base 10).
-func (b *Buffer) AppendUint(i uint64) {
- b.bs = strconv.AppendUint(b.bs, i, 10)
-}
-
-// AppendBool appends a bool to the underlying buffer.
-func (b *Buffer) AppendBool(v bool) {
- b.bs = strconv.AppendBool(b.bs, v)
-}
-
-// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN
-// or +/- Inf.
-func (b *Buffer) AppendFloat(f float64, bitSize int) {
- b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
-}
-
-// Len returns the length of the underlying byte slice.
-func (b *Buffer) Len() int {
- return len(b.bs)
-}
-
-// Cap returns the capacity of the underlying byte slice.
-func (b *Buffer) Cap() int {
- return cap(b.bs)
-}
-
-// Bytes returns a mutable reference to the underlying byte slice.
-func (b *Buffer) Bytes() []byte {
- return b.bs
-}
-
-// String returns a string copy of the underlying byte slice.
-func (b *Buffer) String() string {
- return string(b.bs)
-}
-
-// Reset resets the underlying byte slice. Subsequent writes re-use the slice's
-// backing array.
-func (b *Buffer) Reset() {
- b.bs = b.bs[:0]
-}
-
-// Write implements io.Writer.
-func (b *Buffer) Write(bs []byte) (int, error) {
- b.bs = append(b.bs, bs...)
- return len(bs), nil
-}
-
-// TrimNewline trims any final "\n" byte from the end of the buffer.
-func (b *Buffer) TrimNewline() {
- if i := len(b.bs) - 1; i >= 0 {
- if b.bs[i] == '\n' {
- b.bs = b.bs[:i]
- }
- }
-}
-
-// Free returns the Buffer to its Pool.
-//
-// Callers must not retain references to the Buffer after calling Free.
-func (b *Buffer) Free() {
- b.pool.put(b)
-}
diff --git a/vendor/go.uber.org/zap/buffer/pool.go b/vendor/go.uber.org/zap/buffer/pool.go
deleted file mode 100644
index 8fb3e202cf..0000000000
--- a/vendor/go.uber.org/zap/buffer/pool.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package buffer
-
-import "sync"
-
-// A Pool is a type-safe wrapper around a sync.Pool.
-type Pool struct {
- p *sync.Pool
-}
-
-// NewPool constructs a new Pool.
-func NewPool() Pool {
- return Pool{p: &sync.Pool{
- New: func() interface{} {
- return &Buffer{bs: make([]byte, 0, _size)}
- },
- }}
-}
-
-// Get retrieves a Buffer from the pool, creating one if necessary.
-func (p Pool) Get() *Buffer {
- buf := p.p.Get().(*Buffer)
- buf.Reset()
- buf.pool = p
- return buf
-}
-
-func (p Pool) put(buf *Buffer) {
- p.p.Put(buf)
-}
diff --git a/vendor/go.uber.org/zap/checklicense.sh b/vendor/go.uber.org/zap/checklicense.sh
deleted file mode 100644
index 345ac8b89a..0000000000
--- a/vendor/go.uber.org/zap/checklicense.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash -e
-
-ERROR_COUNT=0
-while read -r file
-do
- case "$(head -1 "${file}")" in
- *"Copyright (c) "*" Uber Technologies, Inc.")
- # everything's cool
- ;;
- *)
- echo "$file is missing license header."
- (( ERROR_COUNT++ ))
- ;;
- esac
-done < <(git ls-files "*\.go")
-
-exit $ERROR_COUNT
diff --git a/vendor/go.uber.org/zap/config.go b/vendor/go.uber.org/zap/config.go
deleted file mode 100644
index 55637fb0b4..0000000000
--- a/vendor/go.uber.org/zap/config.go
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "fmt"
- "sort"
- "time"
-
- "go.uber.org/zap/zapcore"
-)
-
-// SamplingConfig sets a sampling strategy for the logger. Sampling caps the
-// global CPU and I/O load that logging puts on your process while attempting
-// to preserve a representative subset of your logs.
-//
-// If specified, the Sampler will invoke the Hook after each decision.
-//
-// Values configured here are per-second. See zapcore.NewSamplerWithOptions for
-// details.
-type SamplingConfig struct {
- Initial int `json:"initial" yaml:"initial"`
- Thereafter int `json:"thereafter" yaml:"thereafter"`
- Hook func(zapcore.Entry, zapcore.SamplingDecision) `json:"-" yaml:"-"`
-}
-
-// Config offers a declarative way to construct a logger. It doesn't do
-// anything that can't be done with New, Options, and the various
-// zapcore.WriteSyncer and zapcore.Core wrappers, but it's a simpler way to
-// toggle common options.
-//
-// Note that Config intentionally supports only the most common options. More
-// unusual logging setups (logging to network connections or message queues,
-// splitting output between multiple files, etc.) are possible, but require
-// direct use of the zapcore package. For sample code, see the package-level
-// BasicConfiguration and AdvancedConfiguration examples.
-//
-// For an example showing runtime log level changes, see the documentation for
-// AtomicLevel.
-type Config struct {
- // Level is the minimum enabled logging level. Note that this is a dynamic
- // level, so calling Config.Level.SetLevel will atomically change the log
- // level of all loggers descended from this config.
- Level AtomicLevel `json:"level" yaml:"level"`
- // Development puts the logger in development mode, which changes the
- // behavior of DPanicLevel and takes stacktraces more liberally.
- Development bool `json:"development" yaml:"development"`
- // DisableCaller stops annotating logs with the calling function's file
- // name and line number. By default, all logs are annotated.
- DisableCaller bool `json:"disableCaller" yaml:"disableCaller"`
- // DisableStacktrace completely disables automatic stacktrace capturing. By
- // default, stacktraces are captured for WarnLevel and above logs in
- // development and ErrorLevel and above in production.
- DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"`
- // Sampling sets a sampling policy. A nil SamplingConfig disables sampling.
- Sampling *SamplingConfig `json:"sampling" yaml:"sampling"`
- // Encoding sets the logger's encoding. Valid values are "json" and
- // "console", as well as any third-party encodings registered via
- // RegisterEncoder.
- Encoding string `json:"encoding" yaml:"encoding"`
- // EncoderConfig sets options for the chosen encoder. See
- // zapcore.EncoderConfig for details.
- EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"`
- // OutputPaths is a list of URLs or file paths to write logging output to.
- // See Open for details.
- OutputPaths []string `json:"outputPaths" yaml:"outputPaths"`
- // ErrorOutputPaths is a list of URLs to write internal logger errors to.
- // The default is standard error.
- //
- // Note that this setting only affects internal errors; for sample code that
- // sends error-level logs to a different location from info- and debug-level
- // logs, see the package-level AdvancedConfiguration example.
- ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"`
- // InitialFields is a collection of fields to add to the root logger.
- InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"`
-}
-
-// NewProductionEncoderConfig returns an opinionated EncoderConfig for
-// production environments.
-func NewProductionEncoderConfig() zapcore.EncoderConfig {
- return zapcore.EncoderConfig{
- TimeKey: "ts",
- LevelKey: "level",
- NameKey: "logger",
- CallerKey: "caller",
- FunctionKey: zapcore.OmitKey,
- MessageKey: "msg",
- StacktraceKey: "stacktrace",
- LineEnding: zapcore.DefaultLineEnding,
- EncodeLevel: zapcore.LowercaseLevelEncoder,
- EncodeTime: zapcore.EpochTimeEncoder,
- EncodeDuration: zapcore.SecondsDurationEncoder,
- EncodeCaller: zapcore.ShortCallerEncoder,
- }
-}
-
-// NewProductionConfig is a reasonable production logging configuration.
-// Logging is enabled at InfoLevel and above.
-//
-// It uses a JSON encoder, writes to standard error, and enables sampling.
-// Stacktraces are automatically included on logs of ErrorLevel and above.
-func NewProductionConfig() Config {
- return Config{
- Level: NewAtomicLevelAt(InfoLevel),
- Development: false,
- Sampling: &SamplingConfig{
- Initial: 100,
- Thereafter: 100,
- },
- Encoding: "json",
- EncoderConfig: NewProductionEncoderConfig(),
- OutputPaths: []string{"stderr"},
- ErrorOutputPaths: []string{"stderr"},
- }
-}
-
-// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for
-// development environments.
-func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
- return zapcore.EncoderConfig{
- // Keys can be anything except the empty string.
- TimeKey: "T",
- LevelKey: "L",
- NameKey: "N",
- CallerKey: "C",
- FunctionKey: zapcore.OmitKey,
- MessageKey: "M",
- StacktraceKey: "S",
- LineEnding: zapcore.DefaultLineEnding,
- EncodeLevel: zapcore.CapitalLevelEncoder,
- EncodeTime: zapcore.ISO8601TimeEncoder,
- EncodeDuration: zapcore.StringDurationEncoder,
- EncodeCaller: zapcore.ShortCallerEncoder,
- }
-}
-
-// NewDevelopmentConfig is a reasonable development logging configuration.
-// Logging is enabled at DebugLevel and above.
-//
-// It enables development mode (which makes DPanicLevel logs panic), uses a
-// console encoder, writes to standard error, and disables sampling.
-// Stacktraces are automatically included on logs of WarnLevel and above.
-func NewDevelopmentConfig() Config {
- return Config{
- Level: NewAtomicLevelAt(DebugLevel),
- Development: true,
- Encoding: "console",
- EncoderConfig: NewDevelopmentEncoderConfig(),
- OutputPaths: []string{"stderr"},
- ErrorOutputPaths: []string{"stderr"},
- }
-}
-
-// Build constructs a logger from the Config and Options.
-func (cfg Config) Build(opts ...Option) (*Logger, error) {
- enc, err := cfg.buildEncoder()
- if err != nil {
- return nil, err
- }
-
- sink, errSink, err := cfg.openSinks()
- if err != nil {
- return nil, err
- }
-
- if cfg.Level == (AtomicLevel{}) {
- return nil, fmt.Errorf("missing Level")
- }
-
- log := New(
- zapcore.NewCore(enc, sink, cfg.Level),
- cfg.buildOptions(errSink)...,
- )
- if len(opts) > 0 {
- log = log.WithOptions(opts...)
- }
- return log, nil
-}
-
-func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option {
- opts := []Option{ErrorOutput(errSink)}
-
- if cfg.Development {
- opts = append(opts, Development())
- }
-
- if !cfg.DisableCaller {
- opts = append(opts, AddCaller())
- }
-
- stackLevel := ErrorLevel
- if cfg.Development {
- stackLevel = WarnLevel
- }
- if !cfg.DisableStacktrace {
- opts = append(opts, AddStacktrace(stackLevel))
- }
-
- if scfg := cfg.Sampling; scfg != nil {
- opts = append(opts, WrapCore(func(core zapcore.Core) zapcore.Core {
- var samplerOpts []zapcore.SamplerOption
- if scfg.Hook != nil {
- samplerOpts = append(samplerOpts, zapcore.SamplerHook(scfg.Hook))
- }
- return zapcore.NewSamplerWithOptions(
- core,
- time.Second,
- cfg.Sampling.Initial,
- cfg.Sampling.Thereafter,
- samplerOpts...,
- )
- }))
- }
-
- if len(cfg.InitialFields) > 0 {
- fs := make([]Field, 0, len(cfg.InitialFields))
- keys := make([]string, 0, len(cfg.InitialFields))
- for k := range cfg.InitialFields {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- fs = append(fs, Any(k, cfg.InitialFields[k]))
- }
- opts = append(opts, Fields(fs...))
- }
-
- return opts
-}
-
-func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
- sink, closeOut, err := Open(cfg.OutputPaths...)
- if err != nil {
- return nil, nil, err
- }
- errSink, _, err := Open(cfg.ErrorOutputPaths...)
- if err != nil {
- closeOut()
- return nil, nil, err
- }
- return sink, errSink, nil
-}
-
-func (cfg Config) buildEncoder() (zapcore.Encoder, error) {
- return newEncoder(cfg.Encoding, cfg.EncoderConfig)
-}
diff --git a/vendor/go.uber.org/zap/doc.go b/vendor/go.uber.org/zap/doc.go
deleted file mode 100644
index 8638dd1b96..0000000000
--- a/vendor/go.uber.org/zap/doc.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package zap provides fast, structured, leveled logging.
-//
-// For applications that log in the hot path, reflection-based serialization
-// and string formatting are prohibitively expensive - they're CPU-intensive
-// and make many small allocations. Put differently, using json.Marshal and
-// fmt.Fprintf to log tons of interface{} makes your application slow.
-//
-// Zap takes a different approach. It includes a reflection-free,
-// zero-allocation JSON encoder, and the base Logger strives to avoid
-// serialization overhead and allocations wherever possible. By building the
-// high-level SugaredLogger on that foundation, zap lets users choose when
-// they need to count every allocation and when they'd prefer a more familiar,
-// loosely typed API.
-//
-// Choosing a Logger
-//
-// In contexts where performance is nice, but not critical, use the
-// SugaredLogger. It's 4-10x faster than other structured logging packages and
-// supports both structured and printf-style logging. Like log15 and go-kit,
-// the SugaredLogger's structured logging APIs are loosely typed and accept a
-// variadic number of key-value pairs. (For more advanced use cases, they also
-// accept strongly typed fields - see the SugaredLogger.With documentation for
-// details.)
-// sugar := zap.NewExample().Sugar()
-// defer sugar.Sync()
-// sugar.Infow("failed to fetch URL",
-// "url", "http://example.com",
-// "attempt", 3,
-// "backoff", time.Second,
-// )
-// sugar.Infof("failed to fetch URL: %s", "http://example.com")
-//
-// By default, loggers are unbuffered. However, since zap's low-level APIs
-// allow buffering, calling Sync before letting your process exit is a good
-// habit.
-//
-// In the rare contexts where every microsecond and every allocation matter,
-// use the Logger. It's even faster than the SugaredLogger and allocates far
-// less, but it only supports strongly-typed, structured logging.
-// logger := zap.NewExample()
-// defer logger.Sync()
-// logger.Info("failed to fetch URL",
-// zap.String("url", "http://example.com"),
-// zap.Int("attempt", 3),
-// zap.Duration("backoff", time.Second),
-// )
-//
-// Choosing between the Logger and SugaredLogger doesn't need to be an
-// application-wide decision: converting between the two is simple and
-// inexpensive.
-// logger := zap.NewExample()
-// defer logger.Sync()
-// sugar := logger.Sugar()
-// plain := sugar.Desugar()
-//
-// Configuring Zap
-//
-// The simplest way to build a Logger is to use zap's opinionated presets:
-// NewExample, NewProduction, and NewDevelopment. These presets build a logger
-// with a single function call:
-// logger, err := zap.NewProduction()
-// if err != nil {
-// log.Fatalf("can't initialize zap logger: %v", err)
-// }
-// defer logger.Sync()
-//
-// Presets are fine for small projects, but larger projects and organizations
-// naturally require a bit more customization. For most users, zap's Config
-// struct strikes the right balance between flexibility and convenience. See
-// the package-level BasicConfiguration example for sample code.
-//
-// More unusual configurations (splitting output between files, sending logs
-// to a message queue, etc.) are possible, but require direct use of
-// go.uber.org/zap/zapcore. See the package-level AdvancedConfiguration
-// example for sample code.
-//
-// Extending Zap
-//
-// The zap package itself is a relatively thin wrapper around the interfaces
-// in go.uber.org/zap/zapcore. Extending zap to support a new encoding (e.g.,
-// BSON), a new log sink (e.g., Kafka), or something more exotic (perhaps an
-// exception aggregation service, like Sentry or Rollbar) typically requires
-// implementing the zapcore.Encoder, zapcore.WriteSyncer, or zapcore.Core
-// interfaces. See the zapcore documentation for details.
-//
-// Similarly, package authors can use the high-performance Encoder and Core
-// implementations in the zapcore package to build their own loggers.
-//
-// Frequently Asked Questions
-//
-// An FAQ covering everything from installation errors to design decisions is
-// available at https://github.com/uber-go/zap/blob/master/FAQ.md.
-package zap // import "go.uber.org/zap"
diff --git a/vendor/go.uber.org/zap/encoder.go b/vendor/go.uber.org/zap/encoder.go
deleted file mode 100644
index 08ed833543..0000000000
--- a/vendor/go.uber.org/zap/encoder.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "errors"
- "fmt"
- "sync"
-
- "go.uber.org/zap/zapcore"
-)
-
-var (
- errNoEncoderNameSpecified = errors.New("no encoder name specified")
-
- _encoderNameToConstructor = map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error){
- "console": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
- return zapcore.NewConsoleEncoder(encoderConfig), nil
- },
- "json": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
- return zapcore.NewJSONEncoder(encoderConfig), nil
- },
- }
- _encoderMutex sync.RWMutex
-)
-
-// RegisterEncoder registers an encoder constructor, which the Config struct
-// can then reference. By default, the "json" and "console" encoders are
-// registered.
-//
-// Attempting to register an encoder whose name is already taken returns an
-// error.
-func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error {
- _encoderMutex.Lock()
- defer _encoderMutex.Unlock()
- if name == "" {
- return errNoEncoderNameSpecified
- }
- if _, ok := _encoderNameToConstructor[name]; ok {
- return fmt.Errorf("encoder already registered for name %q", name)
- }
- _encoderNameToConstructor[name] = constructor
- return nil
-}
-
-func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
- if encoderConfig.TimeKey != "" && encoderConfig.EncodeTime == nil {
- return nil, fmt.Errorf("missing EncodeTime in EncoderConfig")
- }
-
- _encoderMutex.RLock()
- defer _encoderMutex.RUnlock()
- if name == "" {
- return nil, errNoEncoderNameSpecified
- }
- constructor, ok := _encoderNameToConstructor[name]
- if !ok {
- return nil, fmt.Errorf("no encoder registered for name %q", name)
- }
- return constructor(encoderConfig)
-}
diff --git a/vendor/go.uber.org/zap/error.go b/vendor/go.uber.org/zap/error.go
deleted file mode 100644
index 65982a51e5..0000000000
--- a/vendor/go.uber.org/zap/error.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "sync"
-
- "go.uber.org/zap/zapcore"
-)
-
-var _errArrayElemPool = sync.Pool{New: func() interface{} {
- return &errArrayElem{}
-}}
-
-// Error is shorthand for the common idiom NamedError("error", err).
-func Error(err error) Field {
- return NamedError("error", err)
-}
-
-// NamedError constructs a field that lazily stores err.Error() under the
-// provided key. Errors which also implement fmt.Formatter (like those produced
-// by github.com/pkg/errors) will also have their verbose representation stored
-// under key+"Verbose". If passed a nil error, the field is a no-op.
-//
-// For the common case in which the key is simply "error", the Error function
-// is shorter and less repetitive.
-func NamedError(key string, err error) Field {
- if err == nil {
- return Skip()
- }
- return Field{Key: key, Type: zapcore.ErrorType, Interface: err}
-}
-
-type errArray []error
-
-func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
- for i := range errs {
- if errs[i] == nil {
- continue
- }
- // To represent each error as an object with an "error" attribute and
- // potentially an "errorVerbose" attribute, we need to wrap it in a
- // type that implements LogObjectMarshaler. To prevent this from
- // allocating, pool the wrapper type.
- elem := _errArrayElemPool.Get().(*errArrayElem)
- elem.error = errs[i]
- arr.AppendObject(elem)
- elem.error = nil
- _errArrayElemPool.Put(elem)
- }
- return nil
-}
-
-type errArrayElem struct {
- error
-}
-
-func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error {
- // Re-use the error field's logic, which supports non-standard error types.
- Error(e.error).AddTo(enc)
- return nil
-}
diff --git a/vendor/go.uber.org/zap/field.go b/vendor/go.uber.org/zap/field.go
deleted file mode 100644
index bbb745db5b..0000000000
--- a/vendor/go.uber.org/zap/field.go
+++ /dev/null
@@ -1,549 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "fmt"
- "math"
- "time"
-
- "go.uber.org/zap/zapcore"
-)
-
-// Field is an alias for Field. Aliasing this type dramatically
-// improves the navigability of this package's API documentation.
-type Field = zapcore.Field
-
-var (
- _minTimeInt64 = time.Unix(0, math.MinInt64)
- _maxTimeInt64 = time.Unix(0, math.MaxInt64)
-)
-
-// Skip constructs a no-op field, which is often useful when handling invalid
-// inputs in other Field constructors.
-func Skip() Field {
- return Field{Type: zapcore.SkipType}
-}
-
-// nilField returns a field which will marshal explicitly as nil. See motivation
-// in https://github.com/uber-go/zap/issues/753 . If we ever make breaking
-// changes and add zapcore.NilType and zapcore.ObjectEncoder.AddNil, the
-// implementation here should be changed to reflect that.
-func nilField(key string) Field { return Reflect(key, nil) }
-
-// Binary constructs a field that carries an opaque binary blob.
-//
-// Binary data is serialized in an encoding-appropriate format. For example,
-// zap's JSON encoder base64-encodes binary blobs. To log UTF-8 encoded text,
-// use ByteString.
-func Binary(key string, val []byte) Field {
- return Field{Key: key, Type: zapcore.BinaryType, Interface: val}
-}
-
-// Bool constructs a field that carries a bool.
-func Bool(key string, val bool) Field {
- var ival int64
- if val {
- ival = 1
- }
- return Field{Key: key, Type: zapcore.BoolType, Integer: ival}
-}
-
-// Boolp constructs a field that carries a *bool. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Boolp(key string, val *bool) Field {
- if val == nil {
- return nilField(key)
- }
- return Bool(key, *val)
-}
-
-// ByteString constructs a field that carries UTF-8 encoded text as a []byte.
-// To log opaque binary blobs (which aren't necessarily valid UTF-8), use
-// Binary.
-func ByteString(key string, val []byte) Field {
- return Field{Key: key, Type: zapcore.ByteStringType, Interface: val}
-}
-
-// Complex128 constructs a field that carries a complex number. Unlike most
-// numeric fields, this costs an allocation (to convert the complex128 to
-// interface{}).
-func Complex128(key string, val complex128) Field {
- return Field{Key: key, Type: zapcore.Complex128Type, Interface: val}
-}
-
-// Complex128p constructs a field that carries a *complex128. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Complex128p(key string, val *complex128) Field {
- if val == nil {
- return nilField(key)
- }
- return Complex128(key, *val)
-}
-
-// Complex64 constructs a field that carries a complex number. Unlike most
-// numeric fields, this costs an allocation (to convert the complex64 to
-// interface{}).
-func Complex64(key string, val complex64) Field {
- return Field{Key: key, Type: zapcore.Complex64Type, Interface: val}
-}
-
-// Complex64p constructs a field that carries a *complex64. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Complex64p(key string, val *complex64) Field {
- if val == nil {
- return nilField(key)
- }
- return Complex64(key, *val)
-}
-
-// Float64 constructs a field that carries a float64. The way the
-// floating-point value is represented is encoder-dependent, so marshaling is
-// necessarily lazy.
-func Float64(key string, val float64) Field {
- return Field{Key: key, Type: zapcore.Float64Type, Integer: int64(math.Float64bits(val))}
-}
-
-// Float64p constructs a field that carries a *float64. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Float64p(key string, val *float64) Field {
- if val == nil {
- return nilField(key)
- }
- return Float64(key, *val)
-}
-
-// Float32 constructs a field that carries a float32. The way the
-// floating-point value is represented is encoder-dependent, so marshaling is
-// necessarily lazy.
-func Float32(key string, val float32) Field {
- return Field{Key: key, Type: zapcore.Float32Type, Integer: int64(math.Float32bits(val))}
-}
-
-// Float32p constructs a field that carries a *float32. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Float32p(key string, val *float32) Field {
- if val == nil {
- return nilField(key)
- }
- return Float32(key, *val)
-}
-
-// Int constructs a field with the given key and value.
-func Int(key string, val int) Field {
- return Int64(key, int64(val))
-}
-
-// Intp constructs a field that carries a *int. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Intp(key string, val *int) Field {
- if val == nil {
- return nilField(key)
- }
- return Int(key, *val)
-}
-
-// Int64 constructs a field with the given key and value.
-func Int64(key string, val int64) Field {
- return Field{Key: key, Type: zapcore.Int64Type, Integer: val}
-}
-
-// Int64p constructs a field that carries a *int64. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Int64p(key string, val *int64) Field {
- if val == nil {
- return nilField(key)
- }
- return Int64(key, *val)
-}
-
-// Int32 constructs a field with the given key and value.
-func Int32(key string, val int32) Field {
- return Field{Key: key, Type: zapcore.Int32Type, Integer: int64(val)}
-}
-
-// Int32p constructs a field that carries a *int32. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Int32p(key string, val *int32) Field {
- if val == nil {
- return nilField(key)
- }
- return Int32(key, *val)
-}
-
-// Int16 constructs a field with the given key and value.
-func Int16(key string, val int16) Field {
- return Field{Key: key, Type: zapcore.Int16Type, Integer: int64(val)}
-}
-
-// Int16p constructs a field that carries a *int16. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Int16p(key string, val *int16) Field {
- if val == nil {
- return nilField(key)
- }
- return Int16(key, *val)
-}
-
-// Int8 constructs a field with the given key and value.
-func Int8(key string, val int8) Field {
- return Field{Key: key, Type: zapcore.Int8Type, Integer: int64(val)}
-}
-
-// Int8p constructs a field that carries a *int8. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Int8p(key string, val *int8) Field {
- if val == nil {
- return nilField(key)
- }
- return Int8(key, *val)
-}
-
-// String constructs a field with the given key and value.
-func String(key string, val string) Field {
- return Field{Key: key, Type: zapcore.StringType, String: val}
-}
-
-// Stringp constructs a field that carries a *string. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Stringp(key string, val *string) Field {
- if val == nil {
- return nilField(key)
- }
- return String(key, *val)
-}
-
-// Uint constructs a field with the given key and value.
-func Uint(key string, val uint) Field {
- return Uint64(key, uint64(val))
-}
-
-// Uintp constructs a field that carries a *uint. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Uintp(key string, val *uint) Field {
- if val == nil {
- return nilField(key)
- }
- return Uint(key, *val)
-}
-
-// Uint64 constructs a field with the given key and value.
-func Uint64(key string, val uint64) Field {
- return Field{Key: key, Type: zapcore.Uint64Type, Integer: int64(val)}
-}
-
-// Uint64p constructs a field that carries a *uint64. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Uint64p(key string, val *uint64) Field {
- if val == nil {
- return nilField(key)
- }
- return Uint64(key, *val)
-}
-
-// Uint32 constructs a field with the given key and value.
-func Uint32(key string, val uint32) Field {
- return Field{Key: key, Type: zapcore.Uint32Type, Integer: int64(val)}
-}
-
-// Uint32p constructs a field that carries a *uint32. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Uint32p(key string, val *uint32) Field {
- if val == nil {
- return nilField(key)
- }
- return Uint32(key, *val)
-}
-
-// Uint16 constructs a field with the given key and value.
-func Uint16(key string, val uint16) Field {
- return Field{Key: key, Type: zapcore.Uint16Type, Integer: int64(val)}
-}
-
-// Uint16p constructs a field that carries a *uint16. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Uint16p(key string, val *uint16) Field {
- if val == nil {
- return nilField(key)
- }
- return Uint16(key, *val)
-}
-
-// Uint8 constructs a field with the given key and value.
-func Uint8(key string, val uint8) Field {
- return Field{Key: key, Type: zapcore.Uint8Type, Integer: int64(val)}
-}
-
-// Uint8p constructs a field that carries a *uint8. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Uint8p(key string, val *uint8) Field {
- if val == nil {
- return nilField(key)
- }
- return Uint8(key, *val)
-}
-
-// Uintptr constructs a field with the given key and value.
-func Uintptr(key string, val uintptr) Field {
- return Field{Key: key, Type: zapcore.UintptrType, Integer: int64(val)}
-}
-
-// Uintptrp constructs a field that carries a *uintptr. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Uintptrp(key string, val *uintptr) Field {
- if val == nil {
- return nilField(key)
- }
- return Uintptr(key, *val)
-}
-
-// Reflect constructs a field with the given key and an arbitrary object. It uses
-// an encoding-appropriate, reflection-based function to lazily serialize nearly
-// any object into the logging context, but it's relatively slow and
-// allocation-heavy. Outside tests, Any is always a better choice.
-//
-// If encoding fails (e.g., trying to serialize a map[int]string to JSON), Reflect
-// includes the error message in the final log output.
-func Reflect(key string, val interface{}) Field {
- return Field{Key: key, Type: zapcore.ReflectType, Interface: val}
-}
-
-// Namespace creates a named, isolated scope within the logger's context. All
-// subsequent fields will be added to the new namespace.
-//
-// This helps prevent key collisions when injecting loggers into sub-components
-// or third-party libraries.
-func Namespace(key string) Field {
- return Field{Key: key, Type: zapcore.NamespaceType}
-}
-
-// Stringer constructs a field with the given key and the output of the value's
-// String method. The Stringer's String method is called lazily.
-func Stringer(key string, val fmt.Stringer) Field {
- return Field{Key: key, Type: zapcore.StringerType, Interface: val}
-}
-
-// Time constructs a Field with the given key and value. The encoder
-// controls how the time is serialized.
-func Time(key string, val time.Time) Field {
- if val.Before(_minTimeInt64) || val.After(_maxTimeInt64) {
- return Field{Key: key, Type: zapcore.TimeFullType, Interface: val}
- }
- return Field{Key: key, Type: zapcore.TimeType, Integer: val.UnixNano(), Interface: val.Location()}
-}
-
-// Timep constructs a field that carries a *time.Time. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Timep(key string, val *time.Time) Field {
- if val == nil {
- return nilField(key)
- }
- return Time(key, *val)
-}
-
-// Stack constructs a field that stores a stacktrace of the current goroutine
-// under provided key. Keep in mind that taking a stacktrace is eager and
-// expensive (relatively speaking); this function both makes an allocation and
-// takes about two microseconds.
-func Stack(key string) Field {
- return StackSkip(key, 1) // skip Stack
-}
-
-// StackSkip constructs a field similarly to Stack, but also skips the given
-// number of frames from the top of the stacktrace.
-func StackSkip(key string, skip int) Field {
- // Returning the stacktrace as a string costs an allocation, but saves us
- // from expanding the zapcore.Field union struct to include a byte slice. Since
- // taking a stacktrace is already so expensive (~10us), the extra allocation
- // is okay.
- return String(key, takeStacktrace(skip+1)) // skip StackSkip
-}
-
-// Duration constructs a field with the given key and value. The encoder
-// controls how the duration is serialized.
-func Duration(key string, val time.Duration) Field {
- return Field{Key: key, Type: zapcore.DurationType, Integer: int64(val)}
-}
-
-// Durationp constructs a field that carries a *time.Duration. The returned Field will safely
-// and explicitly represent `nil` when appropriate.
-func Durationp(key string, val *time.Duration) Field {
- if val == nil {
- return nilField(key)
- }
- return Duration(key, *val)
-}
-
-// Object constructs a field with the given key and ObjectMarshaler. It
-// provides a flexible, but still type-safe and efficient, way to add map- or
-// struct-like user-defined types to the logging context. The struct's
-// MarshalLogObject method is called lazily.
-func Object(key string, val zapcore.ObjectMarshaler) Field {
- return Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val}
-}
-
-// Inline constructs a Field that is similar to Object, but it
-// will add the elements of the provided ObjectMarshaler to the
-// current namespace.
-func Inline(val zapcore.ObjectMarshaler) Field {
- return zapcore.Field{
- Type: zapcore.InlineMarshalerType,
- Interface: val,
- }
-}
-
-// Any takes a key and an arbitrary value and chooses the best way to represent
-// them as a field, falling back to a reflection-based approach only if
-// necessary.
-//
-// Since byte/uint8 and rune/int32 are aliases, Any can't differentiate between
-// them. To minimize surprises, []byte values are treated as binary blobs, byte
-// values are treated as uint8, and runes are always treated as integers.
-func Any(key string, value interface{}) Field {
- switch val := value.(type) {
- case zapcore.ObjectMarshaler:
- return Object(key, val)
- case zapcore.ArrayMarshaler:
- return Array(key, val)
- case bool:
- return Bool(key, val)
- case *bool:
- return Boolp(key, val)
- case []bool:
- return Bools(key, val)
- case complex128:
- return Complex128(key, val)
- case *complex128:
- return Complex128p(key, val)
- case []complex128:
- return Complex128s(key, val)
- case complex64:
- return Complex64(key, val)
- case *complex64:
- return Complex64p(key, val)
- case []complex64:
- return Complex64s(key, val)
- case float64:
- return Float64(key, val)
- case *float64:
- return Float64p(key, val)
- case []float64:
- return Float64s(key, val)
- case float32:
- return Float32(key, val)
- case *float32:
- return Float32p(key, val)
- case []float32:
- return Float32s(key, val)
- case int:
- return Int(key, val)
- case *int:
- return Intp(key, val)
- case []int:
- return Ints(key, val)
- case int64:
- return Int64(key, val)
- case *int64:
- return Int64p(key, val)
- case []int64:
- return Int64s(key, val)
- case int32:
- return Int32(key, val)
- case *int32:
- return Int32p(key, val)
- case []int32:
- return Int32s(key, val)
- case int16:
- return Int16(key, val)
- case *int16:
- return Int16p(key, val)
- case []int16:
- return Int16s(key, val)
- case int8:
- return Int8(key, val)
- case *int8:
- return Int8p(key, val)
- case []int8:
- return Int8s(key, val)
- case string:
- return String(key, val)
- case *string:
- return Stringp(key, val)
- case []string:
- return Strings(key, val)
- case uint:
- return Uint(key, val)
- case *uint:
- return Uintp(key, val)
- case []uint:
- return Uints(key, val)
- case uint64:
- return Uint64(key, val)
- case *uint64:
- return Uint64p(key, val)
- case []uint64:
- return Uint64s(key, val)
- case uint32:
- return Uint32(key, val)
- case *uint32:
- return Uint32p(key, val)
- case []uint32:
- return Uint32s(key, val)
- case uint16:
- return Uint16(key, val)
- case *uint16:
- return Uint16p(key, val)
- case []uint16:
- return Uint16s(key, val)
- case uint8:
- return Uint8(key, val)
- case *uint8:
- return Uint8p(key, val)
- case []byte:
- return Binary(key, val)
- case uintptr:
- return Uintptr(key, val)
- case *uintptr:
- return Uintptrp(key, val)
- case []uintptr:
- return Uintptrs(key, val)
- case time.Time:
- return Time(key, val)
- case *time.Time:
- return Timep(key, val)
- case []time.Time:
- return Times(key, val)
- case time.Duration:
- return Duration(key, val)
- case *time.Duration:
- return Durationp(key, val)
- case []time.Duration:
- return Durations(key, val)
- case error:
- return NamedError(key, val)
- case []error:
- return Errors(key, val)
- case fmt.Stringer:
- return Stringer(key, val)
- default:
- return Reflect(key, val)
- }
-}
diff --git a/vendor/go.uber.org/zap/flag.go b/vendor/go.uber.org/zap/flag.go
deleted file mode 100644
index 1312875072..0000000000
--- a/vendor/go.uber.org/zap/flag.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "flag"
-
- "go.uber.org/zap/zapcore"
-)
-
-// LevelFlag uses the standard library's flag.Var to declare a global flag
-// with the specified name, default, and usage guidance. The returned value is
-// a pointer to the value of the flag.
-//
-// If you don't want to use the flag package's global state, you can use any
-// non-nil *Level as a flag.Value with your own *flag.FlagSet.
-func LevelFlag(name string, defaultLevel zapcore.Level, usage string) *zapcore.Level {
- lvl := defaultLevel
- flag.Var(&lvl, name, usage)
- return &lvl
-}
diff --git a/vendor/go.uber.org/zap/glide.yaml b/vendor/go.uber.org/zap/glide.yaml
deleted file mode 100644
index 8e1d05e9ab..0000000000
--- a/vendor/go.uber.org/zap/glide.yaml
+++ /dev/null
@@ -1,34 +0,0 @@
-package: go.uber.org/zap
-license: MIT
-import:
-- package: go.uber.org/atomic
- version: ^1
-- package: go.uber.org/multierr
- version: ^1
-testImport:
-- package: github.com/satori/go.uuid
-- package: github.com/sirupsen/logrus
-- package: github.com/apex/log
- subpackages:
- - handlers/json
-- package: github.com/go-kit/kit
- subpackages:
- - log
-- package: github.com/stretchr/testify
- subpackages:
- - assert
- - require
-- package: gopkg.in/inconshreveable/log15.v2
-- package: github.com/mattn/goveralls
-- package: github.com/pborman/uuid
-- package: github.com/pkg/errors
-- package: github.com/rs/zerolog
-- package: golang.org/x/tools
- subpackages:
- - cover
-- package: golang.org/x/lint
- subpackages:
- - golint
-- package: github.com/axw/gocov
- subpackages:
- - gocov
diff --git a/vendor/go.uber.org/zap/global.go b/vendor/go.uber.org/zap/global.go
deleted file mode 100644
index c1ac0507cd..0000000000
--- a/vendor/go.uber.org/zap/global.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "bytes"
- "fmt"
- "log"
- "os"
- "sync"
-
- "go.uber.org/zap/zapcore"
-)
-
-const (
- _loggerWriterDepth = 2
- _programmerErrorTemplate = "You've found a bug in zap! Please file a bug at " +
- "https://github.com/uber-go/zap/issues/new and reference this error: %v"
-)
-
-var (
- _globalMu sync.RWMutex
- _globalL = NewNop()
- _globalS = _globalL.Sugar()
-)
-
-// L returns the global Logger, which can be reconfigured with ReplaceGlobals.
-// It's safe for concurrent use.
-func L() *Logger {
- _globalMu.RLock()
- l := _globalL
- _globalMu.RUnlock()
- return l
-}
-
-// S returns the global SugaredLogger, which can be reconfigured with
-// ReplaceGlobals. It's safe for concurrent use.
-func S() *SugaredLogger {
- _globalMu.RLock()
- s := _globalS
- _globalMu.RUnlock()
- return s
-}
-
-// ReplaceGlobals replaces the global Logger and SugaredLogger, and returns a
-// function to restore the original values. It's safe for concurrent use.
-func ReplaceGlobals(logger *Logger) func() {
- _globalMu.Lock()
- prev := _globalL
- _globalL = logger
- _globalS = logger.Sugar()
- _globalMu.Unlock()
- return func() { ReplaceGlobals(prev) }
-}
-
-// NewStdLog returns a *log.Logger which writes to the supplied zap Logger at
-// InfoLevel. To redirect the standard library's package-global logging
-// functions, use RedirectStdLog instead.
-func NewStdLog(l *Logger) *log.Logger {
- logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth))
- f := logger.Info
- return log.New(&loggerWriter{f}, "" /* prefix */, 0 /* flags */)
-}
-
-// NewStdLogAt returns *log.Logger which writes to supplied zap logger at
-// required level.
-func NewStdLogAt(l *Logger, level zapcore.Level) (*log.Logger, error) {
- logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth))
- logFunc, err := levelToFunc(logger, level)
- if err != nil {
- return nil, err
- }
- return log.New(&loggerWriter{logFunc}, "" /* prefix */, 0 /* flags */), nil
-}
-
-// RedirectStdLog redirects output from the standard library's package-global
-// logger to the supplied logger at InfoLevel. Since zap already handles caller
-// annotations, timestamps, etc., it automatically disables the standard
-// library's annotations and prefixing.
-//
-// It returns a function to restore the original prefix and flags and reset the
-// standard library's output to os.Stderr.
-func RedirectStdLog(l *Logger) func() {
- f, err := redirectStdLogAt(l, InfoLevel)
- if err != nil {
- // Can't get here, since passing InfoLevel to redirectStdLogAt always
- // works.
- panic(fmt.Sprintf(_programmerErrorTemplate, err))
- }
- return f
-}
-
-// RedirectStdLogAt redirects output from the standard library's package-global
-// logger to the supplied logger at the specified level. Since zap already
-// handles caller annotations, timestamps, etc., it automatically disables the
-// standard library's annotations and prefixing.
-//
-// It returns a function to restore the original prefix and flags and reset the
-// standard library's output to os.Stderr.
-func RedirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) {
- return redirectStdLogAt(l, level)
-}
-
-func redirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) {
- flags := log.Flags()
- prefix := log.Prefix()
- log.SetFlags(0)
- log.SetPrefix("")
- logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth))
- logFunc, err := levelToFunc(logger, level)
- if err != nil {
- return nil, err
- }
- log.SetOutput(&loggerWriter{logFunc})
- return func() {
- log.SetFlags(flags)
- log.SetPrefix(prefix)
- log.SetOutput(os.Stderr)
- }, nil
-}
-
-func levelToFunc(logger *Logger, lvl zapcore.Level) (func(string, ...Field), error) {
- switch lvl {
- case DebugLevel:
- return logger.Debug, nil
- case InfoLevel:
- return logger.Info, nil
- case WarnLevel:
- return logger.Warn, nil
- case ErrorLevel:
- return logger.Error, nil
- case DPanicLevel:
- return logger.DPanic, nil
- case PanicLevel:
- return logger.Panic, nil
- case FatalLevel:
- return logger.Fatal, nil
- }
- return nil, fmt.Errorf("unrecognized level: %q", lvl)
-}
-
-type loggerWriter struct {
- logFunc func(msg string, fields ...Field)
-}
-
-func (l *loggerWriter) Write(p []byte) (int, error) {
- p = bytes.TrimSpace(p)
- l.logFunc(string(p))
- return len(p), nil
-}
diff --git a/vendor/go.uber.org/zap/global_go112.go b/vendor/go.uber.org/zap/global_go112.go
deleted file mode 100644
index 6b5dbda807..0000000000
--- a/vendor/go.uber.org/zap/global_go112.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// See #682 for more information.
-// +build go1.12
-
-package zap
-
-const _stdLogDefaultDepth = 1
diff --git a/vendor/go.uber.org/zap/global_prego112.go b/vendor/go.uber.org/zap/global_prego112.go
deleted file mode 100644
index d3ab9af933..0000000000
--- a/vendor/go.uber.org/zap/global_prego112.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// See #682 for more information.
-// +build !go1.12
-
-package zap
-
-const _stdLogDefaultDepth = 2
diff --git a/vendor/go.uber.org/zap/go.mod b/vendor/go.uber.org/zap/go.mod
deleted file mode 100644
index 6578a35454..0000000000
--- a/vendor/go.uber.org/zap/go.mod
+++ /dev/null
@@ -1,12 +0,0 @@
-module go.uber.org/zap
-
-go 1.13
-
-require (
- github.com/pkg/errors v0.8.1
- github.com/stretchr/testify v1.7.0
- go.uber.org/atomic v1.7.0
- go.uber.org/multierr v1.6.0
- gopkg.in/yaml.v2 v2.2.8
- gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
-)
diff --git a/vendor/go.uber.org/zap/go.sum b/vendor/go.uber.org/zap/go.sum
deleted file mode 100644
index 911a87ae1c..0000000000
--- a/vendor/go.uber.org/zap/go.sum
+++ /dev/null
@@ -1,22 +0,0 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/vendor/go.uber.org/zap/http_handler.go b/vendor/go.uber.org/zap/http_handler.go
deleted file mode 100644
index 1297c33b32..0000000000
--- a/vendor/go.uber.org/zap/http_handler.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "net/http"
-
- "go.uber.org/zap/zapcore"
-)
-
-// ServeHTTP is a simple JSON endpoint that can report on or change the current
-// logging level.
-//
-// GET
-//
-// The GET request returns a JSON description of the current logging level like:
-// {"level":"info"}
-//
-// PUT
-//
-// The PUT request changes the logging level. It is perfectly safe to change the
-// logging level while a program is running. Two content types are supported:
-//
-// Content-Type: application/x-www-form-urlencoded
-//
-// With this content type, the level can be provided through the request body or
-// a query parameter. The log level is URL encoded like:
-//
-// level=debug
-//
-// The request body takes precedence over the query parameter, if both are
-// specified.
-//
-// This content type is the default for a curl PUT request. Following are two
-// example curl requests that both set the logging level to debug.
-//
-// curl -X PUT localhost:8080/log/level?level=debug
-// curl -X PUT localhost:8080/log/level -d level=debug
-//
-// For any other content type, the payload is expected to be JSON encoded and
-// look like:
-//
-// {"level":"info"}
-//
-// An example curl request could look like this:
-//
-// curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}'
-//
-func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- type errorResponse struct {
- Error string `json:"error"`
- }
- type payload struct {
- Level zapcore.Level `json:"level"`
- }
-
- enc := json.NewEncoder(w)
-
- switch r.Method {
- case http.MethodGet:
- enc.Encode(payload{Level: lvl.Level()})
- case http.MethodPut:
- requestedLvl, err := decodePutRequest(r.Header.Get("Content-Type"), r)
- if err != nil {
- w.WriteHeader(http.StatusBadRequest)
- enc.Encode(errorResponse{Error: err.Error()})
- return
- }
- lvl.SetLevel(requestedLvl)
- enc.Encode(payload{Level: lvl.Level()})
- default:
- w.WriteHeader(http.StatusMethodNotAllowed)
- enc.Encode(errorResponse{
- Error: "Only GET and PUT are supported.",
- })
- }
-}
-
-// Decodes incoming PUT requests and returns the requested logging level.
-func decodePutRequest(contentType string, r *http.Request) (zapcore.Level, error) {
- if contentType == "application/x-www-form-urlencoded" {
- return decodePutURL(r)
- }
- return decodePutJSON(r.Body)
-}
-
-func decodePutURL(r *http.Request) (zapcore.Level, error) {
- lvl := r.FormValue("level")
- if lvl == "" {
- return 0, fmt.Errorf("must specify logging level")
- }
- var l zapcore.Level
- if err := l.UnmarshalText([]byte(lvl)); err != nil {
- return 0, err
- }
- return l, nil
-}
-
-func decodePutJSON(body io.Reader) (zapcore.Level, error) {
- var pld struct {
- Level *zapcore.Level `json:"level"`
- }
- if err := json.NewDecoder(body).Decode(&pld); err != nil {
- return 0, fmt.Errorf("malformed request body: %v", err)
- }
- if pld.Level == nil {
- return 0, fmt.Errorf("must specify logging level")
- }
- return *pld.Level, nil
-
-}
diff --git a/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go b/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go
deleted file mode 100644
index dad583aaa5..0000000000
--- a/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package bufferpool houses zap's shared internal buffer pool. Third-party
-// packages can recreate the same functionality with buffers.NewPool.
-package bufferpool
-
-import "go.uber.org/zap/buffer"
-
-var (
- _pool = buffer.NewPool()
- // Get retrieves a buffer from the pool, creating one if necessary.
- Get = _pool.Get
-)
diff --git a/vendor/go.uber.org/zap/internal/color/color.go b/vendor/go.uber.org/zap/internal/color/color.go
deleted file mode 100644
index c4d5d02abc..0000000000
--- a/vendor/go.uber.org/zap/internal/color/color.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package color adds coloring functionality for TTY output.
-package color
-
-import "fmt"
-
-// Foreground colors.
-const (
- Black Color = iota + 30
- Red
- Green
- Yellow
- Blue
- Magenta
- Cyan
- White
-)
-
-// Color represents a text color.
-type Color uint8
-
-// Add adds the coloring to the given string.
-func (c Color) Add(s string) string {
- return fmt.Sprintf("\x1b[%dm%s\x1b[0m", uint8(c), s)
-}
diff --git a/vendor/go.uber.org/zap/internal/exit/exit.go b/vendor/go.uber.org/zap/internal/exit/exit.go
deleted file mode 100644
index dfc5b05feb..0000000000
--- a/vendor/go.uber.org/zap/internal/exit/exit.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package exit provides stubs so that unit tests can exercise code that calls
-// os.Exit(1).
-package exit
-
-import "os"
-
-var real = func() { os.Exit(1) }
-
-// Exit normally terminates the process by calling os.Exit(1). If the package
-// is stubbed, it instead records a call in the testing spy.
-func Exit() {
- real()
-}
-
-// A StubbedExit is a testing fake for os.Exit.
-type StubbedExit struct {
- Exited bool
- prev func()
-}
-
-// Stub substitutes a fake for the call to os.Exit(1).
-func Stub() *StubbedExit {
- s := &StubbedExit{prev: real}
- real = s.exit
- return s
-}
-
-// WithStub runs the supplied function with Exit stubbed. It returns the stub
-// used, so that users can test whether the process would have crashed.
-func WithStub(f func()) *StubbedExit {
- s := Stub()
- defer s.Unstub()
- f()
- return s
-}
-
-// Unstub restores the previous exit function.
-func (se *StubbedExit) Unstub() {
- real = se.prev
-}
-
-func (se *StubbedExit) exit() {
- se.Exited = true
-}
diff --git a/vendor/go.uber.org/zap/level.go b/vendor/go.uber.org/zap/level.go
deleted file mode 100644
index 3567a9a1e6..0000000000
--- a/vendor/go.uber.org/zap/level.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "go.uber.org/atomic"
- "go.uber.org/zap/zapcore"
-)
-
-const (
- // DebugLevel logs are typically voluminous, and are usually disabled in
- // production.
- DebugLevel = zapcore.DebugLevel
- // InfoLevel is the default logging priority.
- InfoLevel = zapcore.InfoLevel
- // WarnLevel logs are more important than Info, but don't need individual
- // human review.
- WarnLevel = zapcore.WarnLevel
- // ErrorLevel logs are high-priority. If an application is running smoothly,
- // it shouldn't generate any error-level logs.
- ErrorLevel = zapcore.ErrorLevel
- // DPanicLevel logs are particularly important errors. In development the
- // logger panics after writing the message.
- DPanicLevel = zapcore.DPanicLevel
- // PanicLevel logs a message, then panics.
- PanicLevel = zapcore.PanicLevel
- // FatalLevel logs a message, then calls os.Exit(1).
- FatalLevel = zapcore.FatalLevel
-)
-
-// LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with
-// an anonymous function.
-//
-// It's particularly useful when splitting log output between different
-// outputs (e.g., standard error and standard out). For sample code, see the
-// package-level AdvancedConfiguration example.
-type LevelEnablerFunc func(zapcore.Level) bool
-
-// Enabled calls the wrapped function.
-func (f LevelEnablerFunc) Enabled(lvl zapcore.Level) bool { return f(lvl) }
-
-// An AtomicLevel is an atomically changeable, dynamic logging level. It lets
-// you safely change the log level of a tree of loggers (the root logger and
-// any children created by adding context) at runtime.
-//
-// The AtomicLevel itself is an http.Handler that serves a JSON endpoint to
-// alter its level.
-//
-// AtomicLevels must be created with the NewAtomicLevel constructor to allocate
-// their internal atomic pointer.
-type AtomicLevel struct {
- l *atomic.Int32
-}
-
-// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging
-// enabled.
-func NewAtomicLevel() AtomicLevel {
- return AtomicLevel{
- l: atomic.NewInt32(int32(InfoLevel)),
- }
-}
-
-// NewAtomicLevelAt is a convenience function that creates an AtomicLevel
-// and then calls SetLevel with the given level.
-func NewAtomicLevelAt(l zapcore.Level) AtomicLevel {
- a := NewAtomicLevel()
- a.SetLevel(l)
- return a
-}
-
-// Enabled implements the zapcore.LevelEnabler interface, which allows the
-// AtomicLevel to be used in place of traditional static levels.
-func (lvl AtomicLevel) Enabled(l zapcore.Level) bool {
- return lvl.Level().Enabled(l)
-}
-
-// Level returns the minimum enabled log level.
-func (lvl AtomicLevel) Level() zapcore.Level {
- return zapcore.Level(int8(lvl.l.Load()))
-}
-
-// SetLevel alters the logging level.
-func (lvl AtomicLevel) SetLevel(l zapcore.Level) {
- lvl.l.Store(int32(l))
-}
-
-// String returns the string representation of the underlying Level.
-func (lvl AtomicLevel) String() string {
- return lvl.Level().String()
-}
-
-// UnmarshalText unmarshals the text to an AtomicLevel. It uses the same text
-// representations as the static zapcore.Levels ("debug", "info", "warn",
-// "error", "dpanic", "panic", and "fatal").
-func (lvl *AtomicLevel) UnmarshalText(text []byte) error {
- if lvl.l == nil {
- lvl.l = &atomic.Int32{}
- }
-
- var l zapcore.Level
- if err := l.UnmarshalText(text); err != nil {
- return err
- }
-
- lvl.SetLevel(l)
- return nil
-}
-
-// MarshalText marshals the AtomicLevel to a byte slice. It uses the same
-// text representation as the static zapcore.Levels ("debug", "info", "warn",
-// "error", "dpanic", "panic", and "fatal").
-func (lvl AtomicLevel) MarshalText() (text []byte, err error) {
- return lvl.Level().MarshalText()
-}
diff --git a/vendor/go.uber.org/zap/logger.go b/vendor/go.uber.org/zap/logger.go
deleted file mode 100644
index 553f258e74..0000000000
--- a/vendor/go.uber.org/zap/logger.go
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "runtime"
- "strings"
- "time"
-
- "go.uber.org/zap/zapcore"
-)
-
-// A Logger provides fast, leveled, structured logging. All methods are safe
-// for concurrent use.
-//
-// The Logger is designed for contexts in which every microsecond and every
-// allocation matters, so its API intentionally favors performance and type
-// safety over brevity. For most applications, the SugaredLogger strikes a
-// better balance between performance and ergonomics.
-type Logger struct {
- core zapcore.Core
-
- development bool
- addCaller bool
- onFatal zapcore.CheckWriteAction // default is WriteThenFatal
-
- name string
- errorOutput zapcore.WriteSyncer
-
- addStack zapcore.LevelEnabler
-
- callerSkip int
-}
-
-// New constructs a new Logger from the provided zapcore.Core and Options. If
-// the passed zapcore.Core is nil, it falls back to using a no-op
-// implementation.
-//
-// This is the most flexible way to construct a Logger, but also the most
-// verbose. For typical use cases, the highly-opinionated presets
-// (NewProduction, NewDevelopment, and NewExample) or the Config struct are
-// more convenient.
-//
-// For sample code, see the package-level AdvancedConfiguration example.
-func New(core zapcore.Core, options ...Option) *Logger {
- if core == nil {
- return NewNop()
- }
- log := &Logger{
- core: core,
- errorOutput: zapcore.Lock(os.Stderr),
- addStack: zapcore.FatalLevel + 1,
- }
- return log.WithOptions(options...)
-}
-
-// NewNop returns a no-op Logger. It never writes out logs or internal errors,
-// and it never runs user-defined hooks.
-//
-// Using WithOptions to replace the Core or error output of a no-op Logger can
-// re-enable logging.
-func NewNop() *Logger {
- return &Logger{
- core: zapcore.NewNopCore(),
- errorOutput: zapcore.AddSync(ioutil.Discard),
- addStack: zapcore.FatalLevel + 1,
- }
-}
-
-// NewProduction builds a sensible production Logger that writes InfoLevel and
-// above logs to standard error as JSON.
-//
-// It's a shortcut for NewProductionConfig().Build(...Option).
-func NewProduction(options ...Option) (*Logger, error) {
- return NewProductionConfig().Build(options...)
-}
-
-// NewDevelopment builds a development Logger that writes DebugLevel and above
-// logs to standard error in a human-friendly format.
-//
-// It's a shortcut for NewDevelopmentConfig().Build(...Option).
-func NewDevelopment(options ...Option) (*Logger, error) {
- return NewDevelopmentConfig().Build(options...)
-}
-
-// NewExample builds a Logger that's designed for use in zap's testable
-// examples. It writes DebugLevel and above logs to standard out as JSON, but
-// omits the timestamp and calling function to keep example output
-// short and deterministic.
-func NewExample(options ...Option) *Logger {
- encoderCfg := zapcore.EncoderConfig{
- MessageKey: "msg",
- LevelKey: "level",
- NameKey: "logger",
- EncodeLevel: zapcore.LowercaseLevelEncoder,
- EncodeTime: zapcore.ISO8601TimeEncoder,
- EncodeDuration: zapcore.StringDurationEncoder,
- }
- core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderCfg), os.Stdout, DebugLevel)
- return New(core).WithOptions(options...)
-}
-
-// Sugar wraps the Logger to provide a more ergonomic, but slightly slower,
-// API. Sugaring a Logger is quite inexpensive, so it's reasonable for a
-// single application to use both Loggers and SugaredLoggers, converting
-// between them on the boundaries of performance-sensitive code.
-func (log *Logger) Sugar() *SugaredLogger {
- core := log.clone()
- core.callerSkip += 2
- return &SugaredLogger{core}
-}
-
-// Named adds a new path segment to the logger's name. Segments are joined by
-// periods. By default, Loggers are unnamed.
-func (log *Logger) Named(s string) *Logger {
- if s == "" {
- return log
- }
- l := log.clone()
- if log.name == "" {
- l.name = s
- } else {
- l.name = strings.Join([]string{l.name, s}, ".")
- }
- return l
-}
-
-// WithOptions clones the current Logger, applies the supplied Options, and
-// returns the resulting Logger. It's safe to use concurrently.
-func (log *Logger) WithOptions(opts ...Option) *Logger {
- c := log.clone()
- for _, opt := range opts {
- opt.apply(c)
- }
- return c
-}
-
-// With creates a child logger and adds structured context to it. Fields added
-// to the child don't affect the parent, and vice versa.
-func (log *Logger) With(fields ...Field) *Logger {
- if len(fields) == 0 {
- return log
- }
- l := log.clone()
- l.core = l.core.With(fields)
- return l
-}
-
-// Check returns a CheckedEntry if logging a message at the specified level
-// is enabled. It's a completely optional optimization; in high-performance
-// applications, Check can help avoid allocating a slice to hold fields.
-func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
- return log.check(lvl, msg)
-}
-
-// Debug logs a message at DebugLevel. The message includes any fields passed
-// at the log site, as well as any fields accumulated on the logger.
-func (log *Logger) Debug(msg string, fields ...Field) {
- if ce := log.check(DebugLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// Info logs a message at InfoLevel. The message includes any fields passed
-// at the log site, as well as any fields accumulated on the logger.
-func (log *Logger) Info(msg string, fields ...Field) {
- if ce := log.check(InfoLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// Warn logs a message at WarnLevel. The message includes any fields passed
-// at the log site, as well as any fields accumulated on the logger.
-func (log *Logger) Warn(msg string, fields ...Field) {
- if ce := log.check(WarnLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// Error logs a message at ErrorLevel. The message includes any fields passed
-// at the log site, as well as any fields accumulated on the logger.
-func (log *Logger) Error(msg string, fields ...Field) {
- if ce := log.check(ErrorLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// DPanic logs a message at DPanicLevel. The message includes any fields
-// passed at the log site, as well as any fields accumulated on the logger.
-//
-// If the logger is in development mode, it then panics (DPanic means
-// "development panic"). This is useful for catching errors that are
-// recoverable, but shouldn't ever happen.
-func (log *Logger) DPanic(msg string, fields ...Field) {
- if ce := log.check(DPanicLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// Panic logs a message at PanicLevel. The message includes any fields passed
-// at the log site, as well as any fields accumulated on the logger.
-//
-// The logger then panics, even if logging at PanicLevel is disabled.
-func (log *Logger) Panic(msg string, fields ...Field) {
- if ce := log.check(PanicLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// Fatal logs a message at FatalLevel. The message includes any fields passed
-// at the log site, as well as any fields accumulated on the logger.
-//
-// The logger then calls os.Exit(1), even if logging at FatalLevel is
-// disabled.
-func (log *Logger) Fatal(msg string, fields ...Field) {
- if ce := log.check(FatalLevel, msg); ce != nil {
- ce.Write(fields...)
- }
-}
-
-// Sync calls the underlying Core's Sync method, flushing any buffered log
-// entries. Applications should take care to call Sync before exiting.
-func (log *Logger) Sync() error {
- return log.core.Sync()
-}
-
-// Core returns the Logger's underlying zapcore.Core.
-func (log *Logger) Core() zapcore.Core {
- return log.core
-}
-
-func (log *Logger) clone() *Logger {
- copy := *log
- return ©
-}
-
-func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
- // check must always be called directly by a method in the Logger interface
- // (e.g., Check, Info, Fatal).
- const callerSkipOffset = 2
-
- // Check the level first to reduce the cost of disabled log calls.
- // Since Panic and higher may exit, we skip the optimization for those levels.
- if lvl < zapcore.DPanicLevel && !log.core.Enabled(lvl) {
- return nil
- }
-
- // Create basic checked entry thru the core; this will be non-nil if the
- // log message will actually be written somewhere.
- ent := zapcore.Entry{
- LoggerName: log.name,
- Time: time.Now(),
- Level: lvl,
- Message: msg,
- }
- ce := log.core.Check(ent, nil)
- willWrite := ce != nil
-
- // Set up any required terminal behavior.
- switch ent.Level {
- case zapcore.PanicLevel:
- ce = ce.Should(ent, zapcore.WriteThenPanic)
- case zapcore.FatalLevel:
- onFatal := log.onFatal
- // Noop is the default value for CheckWriteAction, and it leads to
- // continued execution after a Fatal which is unexpected.
- if onFatal == zapcore.WriteThenNoop {
- onFatal = zapcore.WriteThenFatal
- }
- ce = ce.Should(ent, onFatal)
- case zapcore.DPanicLevel:
- if log.development {
- ce = ce.Should(ent, zapcore.WriteThenPanic)
- }
- }
-
- // Only do further annotation if we're going to write this message; checked
- // entries that exist only for terminal behavior don't benefit from
- // annotation.
- if !willWrite {
- return ce
- }
-
- // Thread the error output through to the CheckedEntry.
- ce.ErrorOutput = log.errorOutput
- if log.addCaller {
- frame, defined := getCallerFrame(log.callerSkip + callerSkipOffset)
- if !defined {
- fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", time.Now().UTC())
- log.errorOutput.Sync()
- }
-
- ce.Entry.Caller = zapcore.EntryCaller{
- Defined: defined,
- PC: frame.PC,
- File: frame.File,
- Line: frame.Line,
- Function: frame.Function,
- }
- }
- if log.addStack.Enabled(ce.Entry.Level) {
- ce.Entry.Stack = StackSkip("", log.callerSkip+callerSkipOffset).String
- }
-
- return ce
-}
-
-// getCallerFrame gets caller frame. The argument skip is the number of stack
-// frames to ascend, with 0 identifying the caller of getCallerFrame. The
-// boolean ok is false if it was not possible to recover the information.
-//
-// Note: This implementation is similar to runtime.Caller, but it returns the whole frame.
-func getCallerFrame(skip int) (frame runtime.Frame, ok bool) {
- const skipOffset = 2 // skip getCallerFrame and Callers
-
- pc := make([]uintptr, 1)
- numFrames := runtime.Callers(skip+skipOffset, pc)
- if numFrames < 1 {
- return
- }
-
- frame, _ = runtime.CallersFrames(pc).Next()
- return frame, frame.PC != 0
-}
diff --git a/vendor/go.uber.org/zap/options.go b/vendor/go.uber.org/zap/options.go
deleted file mode 100644
index 0135c20923..0000000000
--- a/vendor/go.uber.org/zap/options.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "fmt"
-
- "go.uber.org/zap/zapcore"
-)
-
-// An Option configures a Logger.
-type Option interface {
- apply(*Logger)
-}
-
-// optionFunc wraps a func so it satisfies the Option interface.
-type optionFunc func(*Logger)
-
-func (f optionFunc) apply(log *Logger) {
- f(log)
-}
-
-// WrapCore wraps or replaces the Logger's underlying zapcore.Core.
-func WrapCore(f func(zapcore.Core) zapcore.Core) Option {
- return optionFunc(func(log *Logger) {
- log.core = f(log.core)
- })
-}
-
-// Hooks registers functions which will be called each time the Logger writes
-// out an Entry. Repeated use of Hooks is additive.
-//
-// Hooks are useful for simple side effects, like capturing metrics for the
-// number of emitted logs. More complex side effects, including anything that
-// requires access to the Entry's structured fields, should be implemented as
-// a zapcore.Core instead. See zapcore.RegisterHooks for details.
-func Hooks(hooks ...func(zapcore.Entry) error) Option {
- return optionFunc(func(log *Logger) {
- log.core = zapcore.RegisterHooks(log.core, hooks...)
- })
-}
-
-// Fields adds fields to the Logger.
-func Fields(fs ...Field) Option {
- return optionFunc(func(log *Logger) {
- log.core = log.core.With(fs)
- })
-}
-
-// ErrorOutput sets the destination for errors generated by the Logger. Note
-// that this option only affects internal errors; for sample code that sends
-// error-level logs to a different location from info- and debug-level logs,
-// see the package-level AdvancedConfiguration example.
-//
-// The supplied WriteSyncer must be safe for concurrent use. The Open and
-// zapcore.Lock functions are the simplest ways to protect files with a mutex.
-func ErrorOutput(w zapcore.WriteSyncer) Option {
- return optionFunc(func(log *Logger) {
- log.errorOutput = w
- })
-}
-
-// Development puts the logger in development mode, which makes DPanic-level
-// logs panic instead of simply logging an error.
-func Development() Option {
- return optionFunc(func(log *Logger) {
- log.development = true
- })
-}
-
-// AddCaller configures the Logger to annotate each message with the filename,
-// line number, and function name of zap's caller. See also WithCaller.
-func AddCaller() Option {
- return WithCaller(true)
-}
-
-// WithCaller configures the Logger to annotate each message with the filename,
-// line number, and function name of zap's caller, or not, depending on the
-// value of enabled. This is a generalized form of AddCaller.
-func WithCaller(enabled bool) Option {
- return optionFunc(func(log *Logger) {
- log.addCaller = enabled
- })
-}
-
-// AddCallerSkip increases the number of callers skipped by caller annotation
-// (as enabled by the AddCaller option). When building wrappers around the
-// Logger and SugaredLogger, supplying this Option prevents zap from always
-// reporting the wrapper code as the caller.
-func AddCallerSkip(skip int) Option {
- return optionFunc(func(log *Logger) {
- log.callerSkip += skip
- })
-}
-
-// AddStacktrace configures the Logger to record a stack trace for all messages at
-// or above a given level.
-func AddStacktrace(lvl zapcore.LevelEnabler) Option {
- return optionFunc(func(log *Logger) {
- log.addStack = lvl
- })
-}
-
-// IncreaseLevel increase the level of the logger. It has no effect if
-// the passed in level tries to decrease the level of the logger.
-func IncreaseLevel(lvl zapcore.LevelEnabler) Option {
- return optionFunc(func(log *Logger) {
- core, err := zapcore.NewIncreaseLevelCore(log.core, lvl)
- if err != nil {
- fmt.Fprintf(log.errorOutput, "failed to IncreaseLevel: %v\n", err)
- } else {
- log.core = core
- }
- })
-}
-
-// OnFatal sets the action to take on fatal logs.
-func OnFatal(action zapcore.CheckWriteAction) Option {
- return optionFunc(func(log *Logger) {
- log.onFatal = action
- })
-}
diff --git a/vendor/go.uber.org/zap/sink.go b/vendor/go.uber.org/zap/sink.go
deleted file mode 100644
index df46fa87a7..0000000000
--- a/vendor/go.uber.org/zap/sink.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "errors"
- "fmt"
- "io"
- "net/url"
- "os"
- "strings"
- "sync"
-
- "go.uber.org/zap/zapcore"
-)
-
-const schemeFile = "file"
-
-var (
- _sinkMutex sync.RWMutex
- _sinkFactories map[string]func(*url.URL) (Sink, error) // keyed by scheme
-)
-
-func init() {
- resetSinkRegistry()
-}
-
-func resetSinkRegistry() {
- _sinkMutex.Lock()
- defer _sinkMutex.Unlock()
-
- _sinkFactories = map[string]func(*url.URL) (Sink, error){
- schemeFile: newFileSink,
- }
-}
-
-// Sink defines the interface to write to and close logger destinations.
-type Sink interface {
- zapcore.WriteSyncer
- io.Closer
-}
-
-type nopCloserSink struct{ zapcore.WriteSyncer }
-
-func (nopCloserSink) Close() error { return nil }
-
-type errSinkNotFound struct {
- scheme string
-}
-
-func (e *errSinkNotFound) Error() string {
- return fmt.Sprintf("no sink found for scheme %q", e.scheme)
-}
-
-// RegisterSink registers a user-supplied factory for all sinks with a
-// particular scheme.
-//
-// All schemes must be ASCII, valid under section 3.1 of RFC 3986
-// (https://tools.ietf.org/html/rfc3986#section-3.1), and must not already
-// have a factory registered. Zap automatically registers a factory for the
-// "file" scheme.
-func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {
- _sinkMutex.Lock()
- defer _sinkMutex.Unlock()
-
- if scheme == "" {
- return errors.New("can't register a sink factory for empty string")
- }
- normalized, err := normalizeScheme(scheme)
- if err != nil {
- return fmt.Errorf("%q is not a valid scheme: %v", scheme, err)
- }
- if _, ok := _sinkFactories[normalized]; ok {
- return fmt.Errorf("sink factory already registered for scheme %q", normalized)
- }
- _sinkFactories[normalized] = factory
- return nil
-}
-
-func newSink(rawURL string) (Sink, error) {
- u, err := url.Parse(rawURL)
- if err != nil {
- return nil, fmt.Errorf("can't parse %q as a URL: %v", rawURL, err)
- }
- if u.Scheme == "" {
- u.Scheme = schemeFile
- }
-
- _sinkMutex.RLock()
- factory, ok := _sinkFactories[u.Scheme]
- _sinkMutex.RUnlock()
- if !ok {
- return nil, &errSinkNotFound{u.Scheme}
- }
- return factory(u)
-}
-
-func newFileSink(u *url.URL) (Sink, error) {
- if u.User != nil {
- return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u)
- }
- if u.Fragment != "" {
- return nil, fmt.Errorf("fragments not allowed with file URLs: got %v", u)
- }
- if u.RawQuery != "" {
- return nil, fmt.Errorf("query parameters not allowed with file URLs: got %v", u)
- }
- // Error messages are better if we check hostname and port separately.
- if u.Port() != "" {
- return nil, fmt.Errorf("ports not allowed with file URLs: got %v", u)
- }
- if hn := u.Hostname(); hn != "" && hn != "localhost" {
- return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u)
- }
- switch u.Path {
- case "stdout":
- return nopCloserSink{os.Stdout}, nil
- case "stderr":
- return nopCloserSink{os.Stderr}, nil
- }
- return os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
-}
-
-func normalizeScheme(s string) (string, error) {
- // https://tools.ietf.org/html/rfc3986#section-3.1
- s = strings.ToLower(s)
- if first := s[0]; 'a' > first || 'z' < first {
- return "", errors.New("must start with a letter")
- }
- for i := 1; i < len(s); i++ { // iterate over bytes, not runes
- c := s[i]
- switch {
- case 'a' <= c && c <= 'z':
- continue
- case '0' <= c && c <= '9':
- continue
- case c == '.' || c == '+' || c == '-':
- continue
- }
- return "", fmt.Errorf("may not contain %q", c)
- }
- return s, nil
-}
diff --git a/vendor/go.uber.org/zap/stacktrace.go b/vendor/go.uber.org/zap/stacktrace.go
deleted file mode 100644
index 0cf8c1ddff..0000000000
--- a/vendor/go.uber.org/zap/stacktrace.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "runtime"
- "sync"
-
- "go.uber.org/zap/internal/bufferpool"
-)
-
-var (
- _stacktracePool = sync.Pool{
- New: func() interface{} {
- return newProgramCounters(64)
- },
- }
-)
-
-func takeStacktrace(skip int) string {
- buffer := bufferpool.Get()
- defer buffer.Free()
- programCounters := _stacktracePool.Get().(*programCounters)
- defer _stacktracePool.Put(programCounters)
-
- var numFrames int
- for {
- // Skip the call to runtime.Callers and takeStacktrace so that the
- // program counters start at the caller of takeStacktrace.
- numFrames = runtime.Callers(skip+2, programCounters.pcs)
- if numFrames < len(programCounters.pcs) {
- break
- }
- // Don't put the too-short counter slice back into the pool; this lets
- // the pool adjust if we consistently take deep stacktraces.
- programCounters = newProgramCounters(len(programCounters.pcs) * 2)
- }
-
- i := 0
- frames := runtime.CallersFrames(programCounters.pcs[:numFrames])
-
- // Note: On the last iteration, frames.Next() returns false, with a valid
- // frame, but we ignore this frame. The last frame is a a runtime frame which
- // adds noise, since it's only either runtime.main or runtime.goexit.
- for frame, more := frames.Next(); more; frame, more = frames.Next() {
- if i != 0 {
- buffer.AppendByte('\n')
- }
- i++
- buffer.AppendString(frame.Function)
- buffer.AppendByte('\n')
- buffer.AppendByte('\t')
- buffer.AppendString(frame.File)
- buffer.AppendByte(':')
- buffer.AppendInt(int64(frame.Line))
- }
-
- return buffer.String()
-}
-
-type programCounters struct {
- pcs []uintptr
-}
-
-func newProgramCounters(size int) *programCounters {
- return &programCounters{make([]uintptr, size)}
-}
diff --git a/vendor/go.uber.org/zap/sugar.go b/vendor/go.uber.org/zap/sugar.go
deleted file mode 100644
index 4084dada79..0000000000
--- a/vendor/go.uber.org/zap/sugar.go
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "fmt"
-
- "go.uber.org/zap/zapcore"
-
- "go.uber.org/multierr"
-)
-
-const (
- _oddNumberErrMsg = "Ignored key without a value."
- _nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."
-)
-
-// A SugaredLogger wraps the base Logger functionality in a slower, but less
-// verbose, API. Any Logger can be converted to a SugaredLogger with its Sugar
-// method.
-//
-// Unlike the Logger, the SugaredLogger doesn't insist on structured logging.
-// For each log level, it exposes three methods: one for loosely-typed
-// structured logging, one for println-style formatting, and one for
-// printf-style formatting. For example, SugaredLoggers can produce InfoLevel
-// output with Infow ("info with" structured context), Info, or Infof.
-type SugaredLogger struct {
- base *Logger
-}
-
-// Desugar unwraps a SugaredLogger, exposing the original Logger. Desugaring
-// is quite inexpensive, so it's reasonable for a single application to use
-// both Loggers and SugaredLoggers, converting between them on the boundaries
-// of performance-sensitive code.
-func (s *SugaredLogger) Desugar() *Logger {
- base := s.base.clone()
- base.callerSkip -= 2
- return base
-}
-
-// Named adds a sub-scope to the logger's name. See Logger.Named for details.
-func (s *SugaredLogger) Named(name string) *SugaredLogger {
- return &SugaredLogger{base: s.base.Named(name)}
-}
-
-// With adds a variadic number of fields to the logging context. It accepts a
-// mix of strongly-typed Field objects and loosely-typed key-value pairs. When
-// processing pairs, the first element of the pair is used as the field key
-// and the second as the field value.
-//
-// For example,
-// sugaredLogger.With(
-// "hello", "world",
-// "failure", errors.New("oh no"),
-// Stack(),
-// "count", 42,
-// "user", User{Name: "alice"},
-// )
-// is the equivalent of
-// unsugared.With(
-// String("hello", "world"),
-// String("failure", "oh no"),
-// Stack(),
-// Int("count", 42),
-// Object("user", User{Name: "alice"}),
-// )
-//
-// Note that the keys in key-value pairs should be strings. In development,
-// passing a non-string key panics. In production, the logger is more
-// forgiving: a separate error is logged, but the key-value pair is skipped
-// and execution continues. Passing an orphaned key triggers similar behavior:
-// panics in development and errors in production.
-func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger {
- return &SugaredLogger{base: s.base.With(s.sweetenFields(args)...)}
-}
-
-// Debug uses fmt.Sprint to construct and log a message.
-func (s *SugaredLogger) Debug(args ...interface{}) {
- s.log(DebugLevel, "", args, nil)
-}
-
-// Info uses fmt.Sprint to construct and log a message.
-func (s *SugaredLogger) Info(args ...interface{}) {
- s.log(InfoLevel, "", args, nil)
-}
-
-// Warn uses fmt.Sprint to construct and log a message.
-func (s *SugaredLogger) Warn(args ...interface{}) {
- s.log(WarnLevel, "", args, nil)
-}
-
-// Error uses fmt.Sprint to construct and log a message.
-func (s *SugaredLogger) Error(args ...interface{}) {
- s.log(ErrorLevel, "", args, nil)
-}
-
-// DPanic uses fmt.Sprint to construct and log a message. In development, the
-// logger then panics. (See DPanicLevel for details.)
-func (s *SugaredLogger) DPanic(args ...interface{}) {
- s.log(DPanicLevel, "", args, nil)
-}
-
-// Panic uses fmt.Sprint to construct and log a message, then panics.
-func (s *SugaredLogger) Panic(args ...interface{}) {
- s.log(PanicLevel, "", args, nil)
-}
-
-// Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit.
-func (s *SugaredLogger) Fatal(args ...interface{}) {
- s.log(FatalLevel, "", args, nil)
-}
-
-// Debugf uses fmt.Sprintf to log a templated message.
-func (s *SugaredLogger) Debugf(template string, args ...interface{}) {
- s.log(DebugLevel, template, args, nil)
-}
-
-// Infof uses fmt.Sprintf to log a templated message.
-func (s *SugaredLogger) Infof(template string, args ...interface{}) {
- s.log(InfoLevel, template, args, nil)
-}
-
-// Warnf uses fmt.Sprintf to log a templated message.
-func (s *SugaredLogger) Warnf(template string, args ...interface{}) {
- s.log(WarnLevel, template, args, nil)
-}
-
-// Errorf uses fmt.Sprintf to log a templated message.
-func (s *SugaredLogger) Errorf(template string, args ...interface{}) {
- s.log(ErrorLevel, template, args, nil)
-}
-
-// DPanicf uses fmt.Sprintf to log a templated message. In development, the
-// logger then panics. (See DPanicLevel for details.)
-func (s *SugaredLogger) DPanicf(template string, args ...interface{}) {
- s.log(DPanicLevel, template, args, nil)
-}
-
-// Panicf uses fmt.Sprintf to log a templated message, then panics.
-func (s *SugaredLogger) Panicf(template string, args ...interface{}) {
- s.log(PanicLevel, template, args, nil)
-}
-
-// Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit.
-func (s *SugaredLogger) Fatalf(template string, args ...interface{}) {
- s.log(FatalLevel, template, args, nil)
-}
-
-// Debugw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-//
-// When debug-level logging is disabled, this is much faster than
-// s.With(keysAndValues).Debug(msg)
-func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{}) {
- s.log(DebugLevel, msg, nil, keysAndValues)
-}
-
-// Infow logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{}) {
- s.log(InfoLevel, msg, nil, keysAndValues)
-}
-
-// Warnw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (s *SugaredLogger) Warnw(msg string, keysAndValues ...interface{}) {
- s.log(WarnLevel, msg, nil, keysAndValues)
-}
-
-// Errorw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (s *SugaredLogger) Errorw(msg string, keysAndValues ...interface{}) {
- s.log(ErrorLevel, msg, nil, keysAndValues)
-}
-
-// DPanicw logs a message with some additional context. In development, the
-// logger then panics. (See DPanicLevel for details.) The variadic key-value
-// pairs are treated as they are in With.
-func (s *SugaredLogger) DPanicw(msg string, keysAndValues ...interface{}) {
- s.log(DPanicLevel, msg, nil, keysAndValues)
-}
-
-// Panicw logs a message with some additional context, then panics. The
-// variadic key-value pairs are treated as they are in With.
-func (s *SugaredLogger) Panicw(msg string, keysAndValues ...interface{}) {
- s.log(PanicLevel, msg, nil, keysAndValues)
-}
-
-// Fatalw logs a message with some additional context, then calls os.Exit. The
-// variadic key-value pairs are treated as they are in With.
-func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{}) {
- s.log(FatalLevel, msg, nil, keysAndValues)
-}
-
-// Sync flushes any buffered log entries.
-func (s *SugaredLogger) Sync() error {
- return s.base.Sync()
-}
-
-func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interface{}, context []interface{}) {
- // If logging at this level is completely disabled, skip the overhead of
- // string formatting.
- if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) {
- return
- }
-
- msg := getMessage(template, fmtArgs)
- if ce := s.base.Check(lvl, msg); ce != nil {
- ce.Write(s.sweetenFields(context)...)
- }
-}
-
-// getMessage format with Sprint, Sprintf, or neither.
-func getMessage(template string, fmtArgs []interface{}) string {
- if len(fmtArgs) == 0 {
- return template
- }
-
- if template != "" {
- return fmt.Sprintf(template, fmtArgs...)
- }
-
- if len(fmtArgs) == 1 {
- if str, ok := fmtArgs[0].(string); ok {
- return str
- }
- }
- return fmt.Sprint(fmtArgs...)
-}
-
-func (s *SugaredLogger) sweetenFields(args []interface{}) []Field {
- if len(args) == 0 {
- return nil
- }
-
- // Allocate enough space for the worst case; if users pass only structured
- // fields, we shouldn't penalize them with extra allocations.
- fields := make([]Field, 0, len(args))
- var invalid invalidPairs
-
- for i := 0; i < len(args); {
- // This is a strongly-typed field. Consume it and move on.
- if f, ok := args[i].(Field); ok {
- fields = append(fields, f)
- i++
- continue
- }
-
- // Make sure this element isn't a dangling key.
- if i == len(args)-1 {
- s.base.DPanic(_oddNumberErrMsg, Any("ignored", args[i]))
- break
- }
-
- // Consume this value and the next, treating them as a key-value pair. If the
- // key isn't a string, add this pair to the slice of invalid pairs.
- key, val := args[i], args[i+1]
- if keyStr, ok := key.(string); !ok {
- // Subsequent errors are likely, so allocate once up front.
- if cap(invalid) == 0 {
- invalid = make(invalidPairs, 0, len(args)/2)
- }
- invalid = append(invalid, invalidPair{i, key, val})
- } else {
- fields = append(fields, Any(keyStr, val))
- }
- i += 2
- }
-
- // If we encountered any invalid key-value pairs, log an error.
- if len(invalid) > 0 {
- s.base.DPanic(_nonStringKeyErrMsg, Array("invalid", invalid))
- }
- return fields
-}
-
-type invalidPair struct {
- position int
- key, value interface{}
-}
-
-func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error {
- enc.AddInt64("position", int64(p.position))
- Any("key", p.key).AddTo(enc)
- Any("value", p.value).AddTo(enc)
- return nil
-}
-
-type invalidPairs []invalidPair
-
-func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error {
- var err error
- for i := range ps {
- err = multierr.Append(err, enc.AppendObject(ps[i]))
- }
- return err
-}
diff --git a/vendor/go.uber.org/zap/time.go b/vendor/go.uber.org/zap/time.go
deleted file mode 100644
index c5a1f16225..0000000000
--- a/vendor/go.uber.org/zap/time.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import "time"
-
-func timeToMillis(t time.Time) int64 {
- return t.UnixNano() / int64(time.Millisecond)
-}
diff --git a/vendor/go.uber.org/zap/writer.go b/vendor/go.uber.org/zap/writer.go
deleted file mode 100644
index 86a709ab0b..0000000000
--- a/vendor/go.uber.org/zap/writer.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zap
-
-import (
- "fmt"
- "io"
- "io/ioutil"
-
- "go.uber.org/zap/zapcore"
-
- "go.uber.org/multierr"
-)
-
-// Open is a high-level wrapper that takes a variadic number of URLs, opens or
-// creates each of the specified resources, and combines them into a locked
-// WriteSyncer. It also returns any error encountered and a function to close
-// any opened files.
-//
-// Passing no URLs returns a no-op WriteSyncer. Zap handles URLs without a
-// scheme and URLs with the "file" scheme. Third-party code may register
-// factories for other schemes using RegisterSink.
-//
-// URLs with the "file" scheme must use absolute paths on the local
-// filesystem. No user, password, port, fragments, or query parameters are
-// allowed, and the hostname must be empty or "localhost".
-//
-// Since it's common to write logs to the local filesystem, URLs without a
-// scheme (e.g., "/var/log/foo.log") are treated as local file paths. Without
-// a scheme, the special paths "stdout" and "stderr" are interpreted as
-// os.Stdout and os.Stderr. When specified without a scheme, relative file
-// paths also work.
-func Open(paths ...string) (zapcore.WriteSyncer, func(), error) {
- writers, close, err := open(paths)
- if err != nil {
- return nil, nil, err
- }
-
- writer := CombineWriteSyncers(writers...)
- return writer, close, nil
-}
-
-func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
- writers := make([]zapcore.WriteSyncer, 0, len(paths))
- closers := make([]io.Closer, 0, len(paths))
- close := func() {
- for _, c := range closers {
- c.Close()
- }
- }
-
- var openErr error
- for _, path := range paths {
- sink, err := newSink(path)
- if err != nil {
- openErr = multierr.Append(openErr, fmt.Errorf("couldn't open sink %q: %v", path, err))
- continue
- }
- writers = append(writers, sink)
- closers = append(closers, sink)
- }
- if openErr != nil {
- close()
- return writers, nil, openErr
- }
-
- return writers, close, nil
-}
-
-// CombineWriteSyncers is a utility that combines multiple WriteSyncers into a
-// single, locked WriteSyncer. If no inputs are supplied, it returns a no-op
-// WriteSyncer.
-//
-// It's provided purely as a convenience; the result is no different from
-// using zapcore.NewMultiWriteSyncer and zapcore.Lock individually.
-func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSyncer {
- if len(writers) == 0 {
- return zapcore.AddSync(ioutil.Discard)
- }
- return zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...))
-}
diff --git a/vendor/go.uber.org/zap/zapcore/console_encoder.go b/vendor/go.uber.org/zap/zapcore/console_encoder.go
deleted file mode 100644
index 2307af404c..0000000000
--- a/vendor/go.uber.org/zap/zapcore/console_encoder.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "fmt"
- "sync"
-
- "go.uber.org/zap/buffer"
- "go.uber.org/zap/internal/bufferpool"
-)
-
-var _sliceEncoderPool = sync.Pool{
- New: func() interface{} {
- return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)}
- },
-}
-
-func getSliceEncoder() *sliceArrayEncoder {
- return _sliceEncoderPool.Get().(*sliceArrayEncoder)
-}
-
-func putSliceEncoder(e *sliceArrayEncoder) {
- e.elems = e.elems[:0]
- _sliceEncoderPool.Put(e)
-}
-
-type consoleEncoder struct {
- *jsonEncoder
-}
-
-// NewConsoleEncoder creates an encoder whose output is designed for human -
-// rather than machine - consumption. It serializes the core log entry data
-// (message, level, timestamp, etc.) in a plain-text format and leaves the
-// structured context as JSON.
-//
-// Note that although the console encoder doesn't use the keys specified in the
-// encoder configuration, it will omit any element whose key is set to the empty
-// string.
-func NewConsoleEncoder(cfg EncoderConfig) Encoder {
- if cfg.ConsoleSeparator == "" {
- // Use a default delimiter of '\t' for backwards compatibility
- cfg.ConsoleSeparator = "\t"
- }
- return consoleEncoder{newJSONEncoder(cfg, true)}
-}
-
-func (c consoleEncoder) Clone() Encoder {
- return consoleEncoder{c.jsonEncoder.Clone().(*jsonEncoder)}
-}
-
-func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) {
- line := bufferpool.Get()
-
- // We don't want the entry's metadata to be quoted and escaped (if it's
- // encoded as strings), which means that we can't use the JSON encoder. The
- // simplest option is to use the memory encoder and fmt.Fprint.
- //
- // If this ever becomes a performance bottleneck, we can implement
- // ArrayEncoder for our plain-text format.
- arr := getSliceEncoder()
- if c.TimeKey != "" && c.EncodeTime != nil {
- c.EncodeTime(ent.Time, arr)
- }
- if c.LevelKey != "" && c.EncodeLevel != nil {
- c.EncodeLevel(ent.Level, arr)
- }
- if ent.LoggerName != "" && c.NameKey != "" {
- nameEncoder := c.EncodeName
-
- if nameEncoder == nil {
- // Fall back to FullNameEncoder for backward compatibility.
- nameEncoder = FullNameEncoder
- }
-
- nameEncoder(ent.LoggerName, arr)
- }
- if ent.Caller.Defined {
- if c.CallerKey != "" && c.EncodeCaller != nil {
- c.EncodeCaller(ent.Caller, arr)
- }
- if c.FunctionKey != "" {
- arr.AppendString(ent.Caller.Function)
- }
- }
- for i := range arr.elems {
- if i > 0 {
- line.AppendString(c.ConsoleSeparator)
- }
- fmt.Fprint(line, arr.elems[i])
- }
- putSliceEncoder(arr)
-
- // Add the message itself.
- if c.MessageKey != "" {
- c.addSeparatorIfNecessary(line)
- line.AppendString(ent.Message)
- }
-
- // Add any structured context.
- c.writeContext(line, fields)
-
- // If there's no stacktrace key, honor that; this allows users to force
- // single-line output.
- if ent.Stack != "" && c.StacktraceKey != "" {
- line.AppendByte('\n')
- line.AppendString(ent.Stack)
- }
-
- if c.LineEnding != "" {
- line.AppendString(c.LineEnding)
- } else {
- line.AppendString(DefaultLineEnding)
- }
- return line, nil
-}
-
-func (c consoleEncoder) writeContext(line *buffer.Buffer, extra []Field) {
- context := c.jsonEncoder.Clone().(*jsonEncoder)
- defer func() {
- // putJSONEncoder assumes the buffer is still used, but we write out the buffer so
- // we can free it.
- context.buf.Free()
- putJSONEncoder(context)
- }()
-
- addFields(context, extra)
- context.closeOpenNamespaces()
- if context.buf.Len() == 0 {
- return
- }
-
- c.addSeparatorIfNecessary(line)
- line.AppendByte('{')
- line.Write(context.buf.Bytes())
- line.AppendByte('}')
-}
-
-func (c consoleEncoder) addSeparatorIfNecessary(line *buffer.Buffer) {
- if line.Len() > 0 {
- line.AppendString(c.ConsoleSeparator)
- }
-}
diff --git a/vendor/go.uber.org/zap/zapcore/core.go b/vendor/go.uber.org/zap/zapcore/core.go
deleted file mode 100644
index a1ef8b034b..0000000000
--- a/vendor/go.uber.org/zap/zapcore/core.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-// Core is a minimal, fast logger interface. It's designed for library authors
-// to wrap in a more user-friendly API.
-type Core interface {
- LevelEnabler
-
- // With adds structured context to the Core.
- With([]Field) Core
- // Check determines whether the supplied Entry should be logged (using the
- // embedded LevelEnabler and possibly some extra logic). If the entry
- // should be logged, the Core adds itself to the CheckedEntry and returns
- // the result.
- //
- // Callers must use Check before calling Write.
- Check(Entry, *CheckedEntry) *CheckedEntry
- // Write serializes the Entry and any Fields supplied at the log site and
- // writes them to their destination.
- //
- // If called, Write should always log the Entry and Fields; it should not
- // replicate the logic of Check.
- Write(Entry, []Field) error
- // Sync flushes buffered logs (if any).
- Sync() error
-}
-
-type nopCore struct{}
-
-// NewNopCore returns a no-op Core.
-func NewNopCore() Core { return nopCore{} }
-func (nopCore) Enabled(Level) bool { return false }
-func (n nopCore) With([]Field) Core { return n }
-func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return ce }
-func (nopCore) Write(Entry, []Field) error { return nil }
-func (nopCore) Sync() error { return nil }
-
-// NewCore creates a Core that writes logs to a WriteSyncer.
-func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core {
- return &ioCore{
- LevelEnabler: enab,
- enc: enc,
- out: ws,
- }
-}
-
-type ioCore struct {
- LevelEnabler
- enc Encoder
- out WriteSyncer
-}
-
-func (c *ioCore) With(fields []Field) Core {
- clone := c.clone()
- addFields(clone.enc, fields)
- return clone
-}
-
-func (c *ioCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
- if c.Enabled(ent.Level) {
- return ce.AddCore(ent, c)
- }
- return ce
-}
-
-func (c *ioCore) Write(ent Entry, fields []Field) error {
- buf, err := c.enc.EncodeEntry(ent, fields)
- if err != nil {
- return err
- }
- _, err = c.out.Write(buf.Bytes())
- buf.Free()
- if err != nil {
- return err
- }
- if ent.Level > ErrorLevel {
- // Since we may be crashing the program, sync the output. Ignore Sync
- // errors, pending a clean solution to issue #370.
- c.Sync()
- }
- return nil
-}
-
-func (c *ioCore) Sync() error {
- return c.out.Sync()
-}
-
-func (c *ioCore) clone() *ioCore {
- return &ioCore{
- LevelEnabler: c.LevelEnabler,
- enc: c.enc.Clone(),
- out: c.out,
- }
-}
diff --git a/vendor/go.uber.org/zap/zapcore/doc.go b/vendor/go.uber.org/zap/zapcore/doc.go
deleted file mode 100644
index 31000e91f7..0000000000
--- a/vendor/go.uber.org/zap/zapcore/doc.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package zapcore defines and implements the low-level interfaces upon which
-// zap is built. By providing alternate implementations of these interfaces,
-// external packages can extend zap's capabilities.
-package zapcore // import "go.uber.org/zap/zapcore"
diff --git a/vendor/go.uber.org/zap/zapcore/encoder.go b/vendor/go.uber.org/zap/zapcore/encoder.go
deleted file mode 100644
index 6601ca166c..0000000000
--- a/vendor/go.uber.org/zap/zapcore/encoder.go
+++ /dev/null
@@ -1,443 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "encoding/json"
- "time"
-
- "go.uber.org/zap/buffer"
-)
-
-// DefaultLineEnding defines the default line ending when writing logs.
-// Alternate line endings specified in EncoderConfig can override this
-// behavior.
-const DefaultLineEnding = "\n"
-
-// OmitKey defines the key to use when callers want to remove a key from log output.
-const OmitKey = ""
-
-// A LevelEncoder serializes a Level to a primitive type.
-type LevelEncoder func(Level, PrimitiveArrayEncoder)
-
-// LowercaseLevelEncoder serializes a Level to a lowercase string. For example,
-// InfoLevel is serialized to "info".
-func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
- enc.AppendString(l.String())
-}
-
-// LowercaseColorLevelEncoder serializes a Level to a lowercase string and adds coloring.
-// For example, InfoLevel is serialized to "info" and colored blue.
-func LowercaseColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
- s, ok := _levelToLowercaseColorString[l]
- if !ok {
- s = _unknownLevelColor.Add(l.String())
- }
- enc.AppendString(s)
-}
-
-// CapitalLevelEncoder serializes a Level to an all-caps string. For example,
-// InfoLevel is serialized to "INFO".
-func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
- enc.AppendString(l.CapitalString())
-}
-
-// CapitalColorLevelEncoder serializes a Level to an all-caps string and adds color.
-// For example, InfoLevel is serialized to "INFO" and colored blue.
-func CapitalColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
- s, ok := _levelToCapitalColorString[l]
- if !ok {
- s = _unknownLevelColor.Add(l.CapitalString())
- }
- enc.AppendString(s)
-}
-
-// UnmarshalText unmarshals text to a LevelEncoder. "capital" is unmarshaled to
-// CapitalLevelEncoder, "coloredCapital" is unmarshaled to CapitalColorLevelEncoder,
-// "colored" is unmarshaled to LowercaseColorLevelEncoder, and anything else
-// is unmarshaled to LowercaseLevelEncoder.
-func (e *LevelEncoder) UnmarshalText(text []byte) error {
- switch string(text) {
- case "capital":
- *e = CapitalLevelEncoder
- case "capitalColor":
- *e = CapitalColorLevelEncoder
- case "color":
- *e = LowercaseColorLevelEncoder
- default:
- *e = LowercaseLevelEncoder
- }
- return nil
-}
-
-// A TimeEncoder serializes a time.Time to a primitive type.
-type TimeEncoder func(time.Time, PrimitiveArrayEncoder)
-
-// EpochTimeEncoder serializes a time.Time to a floating-point number of seconds
-// since the Unix epoch.
-func EpochTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
- nanos := t.UnixNano()
- sec := float64(nanos) / float64(time.Second)
- enc.AppendFloat64(sec)
-}
-
-// EpochMillisTimeEncoder serializes a time.Time to a floating-point number of
-// milliseconds since the Unix epoch.
-func EpochMillisTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
- nanos := t.UnixNano()
- millis := float64(nanos) / float64(time.Millisecond)
- enc.AppendFloat64(millis)
-}
-
-// EpochNanosTimeEncoder serializes a time.Time to an integer number of
-// nanoseconds since the Unix epoch.
-func EpochNanosTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
- enc.AppendInt64(t.UnixNano())
-}
-
-func encodeTimeLayout(t time.Time, layout string, enc PrimitiveArrayEncoder) {
- type appendTimeEncoder interface {
- AppendTimeLayout(time.Time, string)
- }
-
- if enc, ok := enc.(appendTimeEncoder); ok {
- enc.AppendTimeLayout(t, layout)
- return
- }
-
- enc.AppendString(t.Format(layout))
-}
-
-// ISO8601TimeEncoder serializes a time.Time to an ISO8601-formatted string
-// with millisecond precision.
-//
-// If enc supports AppendTimeLayout(t time.Time,layout string), it's used
-// instead of appending a pre-formatted string value.
-func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
- encodeTimeLayout(t, "2006-01-02T15:04:05.000Z0700", enc)
-}
-
-// RFC3339TimeEncoder serializes a time.Time to an RFC3339-formatted string.
-//
-// If enc supports AppendTimeLayout(t time.Time,layout string), it's used
-// instead of appending a pre-formatted string value.
-func RFC3339TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
- encodeTimeLayout(t, time.RFC3339, enc)
-}
-
-// RFC3339NanoTimeEncoder serializes a time.Time to an RFC3339-formatted string
-// with nanosecond precision.
-//
-// If enc supports AppendTimeLayout(t time.Time,layout string), it's used
-// instead of appending a pre-formatted string value.
-func RFC3339NanoTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
- encodeTimeLayout(t, time.RFC3339Nano, enc)
-}
-
-// TimeEncoderOfLayout returns TimeEncoder which serializes a time.Time using
-// given layout.
-func TimeEncoderOfLayout(layout string) TimeEncoder {
- return func(t time.Time, enc PrimitiveArrayEncoder) {
- encodeTimeLayout(t, layout, enc)
- }
-}
-
-// UnmarshalText unmarshals text to a TimeEncoder.
-// "rfc3339nano" and "RFC3339Nano" are unmarshaled to RFC3339NanoTimeEncoder.
-// "rfc3339" and "RFC3339" are unmarshaled to RFC3339TimeEncoder.
-// "iso8601" and "ISO8601" are unmarshaled to ISO8601TimeEncoder.
-// "millis" is unmarshaled to EpochMillisTimeEncoder.
-// "nanos" is unmarshaled to EpochNanosEncoder.
-// Anything else is unmarshaled to EpochTimeEncoder.
-func (e *TimeEncoder) UnmarshalText(text []byte) error {
- switch string(text) {
- case "rfc3339nano", "RFC3339Nano":
- *e = RFC3339NanoTimeEncoder
- case "rfc3339", "RFC3339":
- *e = RFC3339TimeEncoder
- case "iso8601", "ISO8601":
- *e = ISO8601TimeEncoder
- case "millis":
- *e = EpochMillisTimeEncoder
- case "nanos":
- *e = EpochNanosTimeEncoder
- default:
- *e = EpochTimeEncoder
- }
- return nil
-}
-
-// UnmarshalYAML unmarshals YAML to a TimeEncoder.
-// If value is an object with a "layout" field, it will be unmarshaled to TimeEncoder with given layout.
-// timeEncoder:
-// layout: 06/01/02 03:04pm
-// If value is string, it uses UnmarshalText.
-// timeEncoder: iso8601
-func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error) error {
- var o struct {
- Layout string `json:"layout" yaml:"layout"`
- }
- if err := unmarshal(&o); err == nil {
- *e = TimeEncoderOfLayout(o.Layout)
- return nil
- }
-
- var s string
- if err := unmarshal(&s); err != nil {
- return err
- }
- return e.UnmarshalText([]byte(s))
-}
-
-// UnmarshalJSON unmarshals JSON to a TimeEncoder as same way UnmarshalYAML does.
-func (e *TimeEncoder) UnmarshalJSON(data []byte) error {
- return e.UnmarshalYAML(func(v interface{}) error {
- return json.Unmarshal(data, v)
- })
-}
-
-// A DurationEncoder serializes a time.Duration to a primitive type.
-type DurationEncoder func(time.Duration, PrimitiveArrayEncoder)
-
-// SecondsDurationEncoder serializes a time.Duration to a floating-point number of seconds elapsed.
-func SecondsDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
- enc.AppendFloat64(float64(d) / float64(time.Second))
-}
-
-// NanosDurationEncoder serializes a time.Duration to an integer number of
-// nanoseconds elapsed.
-func NanosDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
- enc.AppendInt64(int64(d))
-}
-
-// MillisDurationEncoder serializes a time.Duration to an integer number of
-// milliseconds elapsed.
-func MillisDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
- enc.AppendInt64(d.Nanoseconds() / 1e6)
-}
-
-// StringDurationEncoder serializes a time.Duration using its built-in String
-// method.
-func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
- enc.AppendString(d.String())
-}
-
-// UnmarshalText unmarshals text to a DurationEncoder. "string" is unmarshaled
-// to StringDurationEncoder, and anything else is unmarshaled to
-// NanosDurationEncoder.
-func (e *DurationEncoder) UnmarshalText(text []byte) error {
- switch string(text) {
- case "string":
- *e = StringDurationEncoder
- case "nanos":
- *e = NanosDurationEncoder
- case "ms":
- *e = MillisDurationEncoder
- default:
- *e = SecondsDurationEncoder
- }
- return nil
-}
-
-// A CallerEncoder serializes an EntryCaller to a primitive type.
-type CallerEncoder func(EntryCaller, PrimitiveArrayEncoder)
-
-// FullCallerEncoder serializes a caller in /full/path/to/package/file:line
-// format.
-func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) {
- // TODO: consider using a byte-oriented API to save an allocation.
- enc.AppendString(caller.String())
-}
-
-// ShortCallerEncoder serializes a caller in package/file:line format, trimming
-// all but the final directory from the full path.
-func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) {
- // TODO: consider using a byte-oriented API to save an allocation.
- enc.AppendString(caller.TrimmedPath())
-}
-
-// UnmarshalText unmarshals text to a CallerEncoder. "full" is unmarshaled to
-// FullCallerEncoder and anything else is unmarshaled to ShortCallerEncoder.
-func (e *CallerEncoder) UnmarshalText(text []byte) error {
- switch string(text) {
- case "full":
- *e = FullCallerEncoder
- default:
- *e = ShortCallerEncoder
- }
- return nil
-}
-
-// A NameEncoder serializes a period-separated logger name to a primitive
-// type.
-type NameEncoder func(string, PrimitiveArrayEncoder)
-
-// FullNameEncoder serializes the logger name as-is.
-func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder) {
- enc.AppendString(loggerName)
-}
-
-// UnmarshalText unmarshals text to a NameEncoder. Currently, everything is
-// unmarshaled to FullNameEncoder.
-func (e *NameEncoder) UnmarshalText(text []byte) error {
- switch string(text) {
- case "full":
- *e = FullNameEncoder
- default:
- *e = FullNameEncoder
- }
- return nil
-}
-
-// An EncoderConfig allows users to configure the concrete encoders supplied by
-// zapcore.
-type EncoderConfig struct {
- // Set the keys used for each log entry. If any key is empty, that portion
- // of the entry is omitted.
- MessageKey string `json:"messageKey" yaml:"messageKey"`
- LevelKey string `json:"levelKey" yaml:"levelKey"`
- TimeKey string `json:"timeKey" yaml:"timeKey"`
- NameKey string `json:"nameKey" yaml:"nameKey"`
- CallerKey string `json:"callerKey" yaml:"callerKey"`
- FunctionKey string `json:"functionKey" yaml:"functionKey"`
- StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"`
- LineEnding string `json:"lineEnding" yaml:"lineEnding"`
- // Configure the primitive representations of common complex types. For
- // example, some users may want all time.Times serialized as floating-point
- // seconds since epoch, while others may prefer ISO8601 strings.
- EncodeLevel LevelEncoder `json:"levelEncoder" yaml:"levelEncoder"`
- EncodeTime TimeEncoder `json:"timeEncoder" yaml:"timeEncoder"`
- EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"`
- EncodeCaller CallerEncoder `json:"callerEncoder" yaml:"callerEncoder"`
- // Unlike the other primitive type encoders, EncodeName is optional. The
- // zero value falls back to FullNameEncoder.
- EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"`
- // Configures the field separator used by the console encoder. Defaults
- // to tab.
- ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"`
-}
-
-// ObjectEncoder is a strongly-typed, encoding-agnostic interface for adding a
-// map- or struct-like object to the logging context. Like maps, ObjectEncoders
-// aren't safe for concurrent use (though typical use shouldn't require locks).
-type ObjectEncoder interface {
- // Logging-specific marshalers.
- AddArray(key string, marshaler ArrayMarshaler) error
- AddObject(key string, marshaler ObjectMarshaler) error
-
- // Built-in types.
- AddBinary(key string, value []byte) // for arbitrary bytes
- AddByteString(key string, value []byte) // for UTF-8 encoded bytes
- AddBool(key string, value bool)
- AddComplex128(key string, value complex128)
- AddComplex64(key string, value complex64)
- AddDuration(key string, value time.Duration)
- AddFloat64(key string, value float64)
- AddFloat32(key string, value float32)
- AddInt(key string, value int)
- AddInt64(key string, value int64)
- AddInt32(key string, value int32)
- AddInt16(key string, value int16)
- AddInt8(key string, value int8)
- AddString(key, value string)
- AddTime(key string, value time.Time)
- AddUint(key string, value uint)
- AddUint64(key string, value uint64)
- AddUint32(key string, value uint32)
- AddUint16(key string, value uint16)
- AddUint8(key string, value uint8)
- AddUintptr(key string, value uintptr)
-
- // AddReflected uses reflection to serialize arbitrary objects, so it can be
- // slow and allocation-heavy.
- AddReflected(key string, value interface{}) error
- // OpenNamespace opens an isolated namespace where all subsequent fields will
- // be added. Applications can use namespaces to prevent key collisions when
- // injecting loggers into sub-components or third-party libraries.
- OpenNamespace(key string)
-}
-
-// ArrayEncoder is a strongly-typed, encoding-agnostic interface for adding
-// array-like objects to the logging context. Of note, it supports mixed-type
-// arrays even though they aren't typical in Go. Like slices, ArrayEncoders
-// aren't safe for concurrent use (though typical use shouldn't require locks).
-type ArrayEncoder interface {
- // Built-in types.
- PrimitiveArrayEncoder
-
- // Time-related types.
- AppendDuration(time.Duration)
- AppendTime(time.Time)
-
- // Logging-specific marshalers.
- AppendArray(ArrayMarshaler) error
- AppendObject(ObjectMarshaler) error
-
- // AppendReflected uses reflection to serialize arbitrary objects, so it's
- // slow and allocation-heavy.
- AppendReflected(value interface{}) error
-}
-
-// PrimitiveArrayEncoder is the subset of the ArrayEncoder interface that deals
-// only in Go's built-in types. It's included only so that Duration- and
-// TimeEncoders cannot trigger infinite recursion.
-type PrimitiveArrayEncoder interface {
- // Built-in types.
- AppendBool(bool)
- AppendByteString([]byte) // for UTF-8 encoded bytes
- AppendComplex128(complex128)
- AppendComplex64(complex64)
- AppendFloat64(float64)
- AppendFloat32(float32)
- AppendInt(int)
- AppendInt64(int64)
- AppendInt32(int32)
- AppendInt16(int16)
- AppendInt8(int8)
- AppendString(string)
- AppendUint(uint)
- AppendUint64(uint64)
- AppendUint32(uint32)
- AppendUint16(uint16)
- AppendUint8(uint8)
- AppendUintptr(uintptr)
-}
-
-// Encoder is a format-agnostic interface for all log entry marshalers. Since
-// log encoders don't need to support the same wide range of use cases as
-// general-purpose marshalers, it's possible to make them faster and
-// lower-allocation.
-//
-// Implementations of the ObjectEncoder interface's methods can, of course,
-// freely modify the receiver. However, the Clone and EncodeEntry methods will
-// be called concurrently and shouldn't modify the receiver.
-type Encoder interface {
- ObjectEncoder
-
- // Clone copies the encoder, ensuring that adding fields to the copy doesn't
- // affect the original.
- Clone() Encoder
-
- // EncodeEntry encodes an entry and fields, along with any accumulated
- // context, into a byte buffer and returns it. Any fields that are empty,
- // including fields on the `Entry` type, should be omitted.
- EncodeEntry(Entry, []Field) (*buffer.Buffer, error)
-}
diff --git a/vendor/go.uber.org/zap/zapcore/entry.go b/vendor/go.uber.org/zap/zapcore/entry.go
deleted file mode 100644
index 4aa8b4f90b..0000000000
--- a/vendor/go.uber.org/zap/zapcore/entry.go
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "fmt"
- "runtime"
- "strings"
- "sync"
- "time"
-
- "go.uber.org/zap/internal/bufferpool"
- "go.uber.org/zap/internal/exit"
-
- "go.uber.org/multierr"
-)
-
-var (
- _cePool = sync.Pool{New: func() interface{} {
- // Pre-allocate some space for cores.
- return &CheckedEntry{
- cores: make([]Core, 4),
- }
- }}
-)
-
-func getCheckedEntry() *CheckedEntry {
- ce := _cePool.Get().(*CheckedEntry)
- ce.reset()
- return ce
-}
-
-func putCheckedEntry(ce *CheckedEntry) {
- if ce == nil {
- return
- }
- _cePool.Put(ce)
-}
-
-// NewEntryCaller makes an EntryCaller from the return signature of
-// runtime.Caller.
-func NewEntryCaller(pc uintptr, file string, line int, ok bool) EntryCaller {
- if !ok {
- return EntryCaller{}
- }
- return EntryCaller{
- PC: pc,
- File: file,
- Line: line,
- Defined: true,
- }
-}
-
-// EntryCaller represents the caller of a logging function.
-type EntryCaller struct {
- Defined bool
- PC uintptr
- File string
- Line int
- Function string
-}
-
-// String returns the full path and line number of the caller.
-func (ec EntryCaller) String() string {
- return ec.FullPath()
-}
-
-// FullPath returns a /full/path/to/package/file:line description of the
-// caller.
-func (ec EntryCaller) FullPath() string {
- if !ec.Defined {
- return "undefined"
- }
- buf := bufferpool.Get()
- buf.AppendString(ec.File)
- buf.AppendByte(':')
- buf.AppendInt(int64(ec.Line))
- caller := buf.String()
- buf.Free()
- return caller
-}
-
-// TrimmedPath returns a package/file:line description of the caller,
-// preserving only the leaf directory name and file name.
-func (ec EntryCaller) TrimmedPath() string {
- if !ec.Defined {
- return "undefined"
- }
- // nb. To make sure we trim the path correctly on Windows too, we
- // counter-intuitively need to use '/' and *not* os.PathSeparator here,
- // because the path given originates from Go stdlib, specifically
- // runtime.Caller() which (as of Mar/17) returns forward slashes even on
- // Windows.
- //
- // See https://github.com/golang/go/issues/3335
- // and https://github.com/golang/go/issues/18151
- //
- // for discussion on the issue on Go side.
- //
- // Find the last separator.
- //
- idx := strings.LastIndexByte(ec.File, '/')
- if idx == -1 {
- return ec.FullPath()
- }
- // Find the penultimate separator.
- idx = strings.LastIndexByte(ec.File[:idx], '/')
- if idx == -1 {
- return ec.FullPath()
- }
- buf := bufferpool.Get()
- // Keep everything after the penultimate separator.
- buf.AppendString(ec.File[idx+1:])
- buf.AppendByte(':')
- buf.AppendInt(int64(ec.Line))
- caller := buf.String()
- buf.Free()
- return caller
-}
-
-// An Entry represents a complete log message. The entry's structured context
-// is already serialized, but the log level, time, message, and call site
-// information are available for inspection and modification. Any fields left
-// empty will be omitted when encoding.
-//
-// Entries are pooled, so any functions that accept them MUST be careful not to
-// retain references to them.
-type Entry struct {
- Level Level
- Time time.Time
- LoggerName string
- Message string
- Caller EntryCaller
- Stack string
-}
-
-// CheckWriteAction indicates what action to take after a log entry is
-// processed. Actions are ordered in increasing severity.
-type CheckWriteAction uint8
-
-const (
- // WriteThenNoop indicates that nothing special needs to be done. It's the
- // default behavior.
- WriteThenNoop CheckWriteAction = iota
- // WriteThenGoexit runs runtime.Goexit after Write.
- WriteThenGoexit
- // WriteThenPanic causes a panic after Write.
- WriteThenPanic
- // WriteThenFatal causes a fatal os.Exit after Write.
- WriteThenFatal
-)
-
-// CheckedEntry is an Entry together with a collection of Cores that have
-// already agreed to log it.
-//
-// CheckedEntry references should be created by calling AddCore or Should on a
-// nil *CheckedEntry. References are returned to a pool after Write, and MUST
-// NOT be retained after calling their Write method.
-type CheckedEntry struct {
- Entry
- ErrorOutput WriteSyncer
- dirty bool // best-effort detection of pool misuse
- should CheckWriteAction
- cores []Core
-}
-
-func (ce *CheckedEntry) reset() {
- ce.Entry = Entry{}
- ce.ErrorOutput = nil
- ce.dirty = false
- ce.should = WriteThenNoop
- for i := range ce.cores {
- // don't keep references to cores
- ce.cores[i] = nil
- }
- ce.cores = ce.cores[:0]
-}
-
-// Write writes the entry to the stored Cores, returns any errors, and returns
-// the CheckedEntry reference to a pool for immediate re-use. Finally, it
-// executes any required CheckWriteAction.
-func (ce *CheckedEntry) Write(fields ...Field) {
- if ce == nil {
- return
- }
-
- if ce.dirty {
- if ce.ErrorOutput != nil {
- // Make a best effort to detect unsafe re-use of this CheckedEntry.
- // If the entry is dirty, log an internal error; because the
- // CheckedEntry is being used after it was returned to the pool,
- // the message may be an amalgamation from multiple call sites.
- fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", time.Now(), ce.Entry)
- ce.ErrorOutput.Sync()
- }
- return
- }
- ce.dirty = true
-
- var err error
- for i := range ce.cores {
- err = multierr.Append(err, ce.cores[i].Write(ce.Entry, fields))
- }
- if ce.ErrorOutput != nil {
- if err != nil {
- fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", time.Now(), err)
- ce.ErrorOutput.Sync()
- }
- }
-
- should, msg := ce.should, ce.Message
- putCheckedEntry(ce)
-
- switch should {
- case WriteThenPanic:
- panic(msg)
- case WriteThenFatal:
- exit.Exit()
- case WriteThenGoexit:
- runtime.Goexit()
- }
-}
-
-// AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be
-// used by Core.Check implementations, and is safe to call on nil CheckedEntry
-// references.
-func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry {
- if ce == nil {
- ce = getCheckedEntry()
- ce.Entry = ent
- }
- ce.cores = append(ce.cores, core)
- return ce
-}
-
-// Should sets this CheckedEntry's CheckWriteAction, which controls whether a
-// Core will panic or fatal after writing this log entry. Like AddCore, it's
-// safe to call on nil CheckedEntry references.
-func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry {
- if ce == nil {
- ce = getCheckedEntry()
- ce.Entry = ent
- }
- ce.should = should
- return ce
-}
diff --git a/vendor/go.uber.org/zap/zapcore/error.go b/vendor/go.uber.org/zap/zapcore/error.go
deleted file mode 100644
index f2a07d7864..0000000000
--- a/vendor/go.uber.org/zap/zapcore/error.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "fmt"
- "reflect"
- "sync"
-)
-
-// Encodes the given error into fields of an object. A field with the given
-// name is added for the error message.
-//
-// If the error implements fmt.Formatter, a field with the name ${key}Verbose
-// is also added with the full verbose error message.
-//
-// Finally, if the error implements errorGroup (from go.uber.org/multierr) or
-// causer (from github.com/pkg/errors), a ${key}Causes field is added with an
-// array of objects containing the errors this error was comprised of.
-//
-// {
-// "error": err.Error(),
-// "errorVerbose": fmt.Sprintf("%+v", err),
-// "errorCauses": [
-// ...
-// ],
-// }
-func encodeError(key string, err error, enc ObjectEncoder) (retErr error) {
- // Try to capture panics (from nil references or otherwise) when calling
- // the Error() method
- defer func() {
- if rerr := recover(); rerr != nil {
- // If it's a nil pointer, just say "". The likeliest causes are a
- // error that fails to guard against nil or a nil pointer for a
- // value receiver, and in either case, "" is a nice result.
- if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
- enc.AddString(key, "")
- return
- }
-
- retErr = fmt.Errorf("PANIC=%v", rerr)
- }
- }()
-
- basic := err.Error()
- enc.AddString(key, basic)
-
- switch e := err.(type) {
- case errorGroup:
- return enc.AddArray(key+"Causes", errArray(e.Errors()))
- case fmt.Formatter:
- verbose := fmt.Sprintf("%+v", e)
- if verbose != basic {
- // This is a rich error type, like those produced by
- // github.com/pkg/errors.
- enc.AddString(key+"Verbose", verbose)
- }
- }
- return nil
-}
-
-type errorGroup interface {
- // Provides read-only access to the underlying list of errors, preferably
- // without causing any allocs.
- Errors() []error
-}
-
-// Note that errArry and errArrayElem are very similar to the version
-// implemented in the top-level error.go file. We can't re-use this because
-// that would require exporting errArray as part of the zapcore API.
-
-// Encodes a list of errors using the standard error encoding logic.
-type errArray []error
-
-func (errs errArray) MarshalLogArray(arr ArrayEncoder) error {
- for i := range errs {
- if errs[i] == nil {
- continue
- }
-
- el := newErrArrayElem(errs[i])
- arr.AppendObject(el)
- el.Free()
- }
- return nil
-}
-
-var _errArrayElemPool = sync.Pool{New: func() interface{} {
- return &errArrayElem{}
-}}
-
-// Encodes any error into a {"error": ...} re-using the same errors logic.
-//
-// May be passed in place of an array to build a single-element array.
-type errArrayElem struct{ err error }
-
-func newErrArrayElem(err error) *errArrayElem {
- e := _errArrayElemPool.Get().(*errArrayElem)
- e.err = err
- return e
-}
-
-func (e *errArrayElem) MarshalLogArray(arr ArrayEncoder) error {
- return arr.AppendObject(e)
-}
-
-func (e *errArrayElem) MarshalLogObject(enc ObjectEncoder) error {
- return encodeError("error", e.err, enc)
-}
-
-func (e *errArrayElem) Free() {
- e.err = nil
- _errArrayElemPool.Put(e)
-}
diff --git a/vendor/go.uber.org/zap/zapcore/field.go b/vendor/go.uber.org/zap/zapcore/field.go
deleted file mode 100644
index 95bdb0a126..0000000000
--- a/vendor/go.uber.org/zap/zapcore/field.go
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "bytes"
- "fmt"
- "math"
- "reflect"
- "time"
-)
-
-// A FieldType indicates which member of the Field union struct should be used
-// and how it should be serialized.
-type FieldType uint8
-
-const (
- // UnknownType is the default field type. Attempting to add it to an encoder will panic.
- UnknownType FieldType = iota
- // ArrayMarshalerType indicates that the field carries an ArrayMarshaler.
- ArrayMarshalerType
- // ObjectMarshalerType indicates that the field carries an ObjectMarshaler.
- ObjectMarshalerType
- // BinaryType indicates that the field carries an opaque binary blob.
- BinaryType
- // BoolType indicates that the field carries a bool.
- BoolType
- // ByteStringType indicates that the field carries UTF-8 encoded bytes.
- ByteStringType
- // Complex128Type indicates that the field carries a complex128.
- Complex128Type
- // Complex64Type indicates that the field carries a complex128.
- Complex64Type
- // DurationType indicates that the field carries a time.Duration.
- DurationType
- // Float64Type indicates that the field carries a float64.
- Float64Type
- // Float32Type indicates that the field carries a float32.
- Float32Type
- // Int64Type indicates that the field carries an int64.
- Int64Type
- // Int32Type indicates that the field carries an int32.
- Int32Type
- // Int16Type indicates that the field carries an int16.
- Int16Type
- // Int8Type indicates that the field carries an int8.
- Int8Type
- // StringType indicates that the field carries a string.
- StringType
- // TimeType indicates that the field carries a time.Time that is
- // representable by a UnixNano() stored as an int64.
- TimeType
- // TimeFullType indicates that the field carries a time.Time stored as-is.
- TimeFullType
- // Uint64Type indicates that the field carries a uint64.
- Uint64Type
- // Uint32Type indicates that the field carries a uint32.
- Uint32Type
- // Uint16Type indicates that the field carries a uint16.
- Uint16Type
- // Uint8Type indicates that the field carries a uint8.
- Uint8Type
- // UintptrType indicates that the field carries a uintptr.
- UintptrType
- // ReflectType indicates that the field carries an interface{}, which should
- // be serialized using reflection.
- ReflectType
- // NamespaceType signals the beginning of an isolated namespace. All
- // subsequent fields should be added to the new namespace.
- NamespaceType
- // StringerType indicates that the field carries a fmt.Stringer.
- StringerType
- // ErrorType indicates that the field carries an error.
- ErrorType
- // SkipType indicates that the field is a no-op.
- SkipType
-
- // InlineMarshalerType indicates that the field carries an ObjectMarshaler
- // that should be inlined.
- InlineMarshalerType
-)
-
-// A Field is a marshaling operation used to add a key-value pair to a logger's
-// context. Most fields are lazily marshaled, so it's inexpensive to add fields
-// to disabled debug-level log statements.
-type Field struct {
- Key string
- Type FieldType
- Integer int64
- String string
- Interface interface{}
-}
-
-// AddTo exports a field through the ObjectEncoder interface. It's primarily
-// useful to library authors, and shouldn't be necessary in most applications.
-func (f Field) AddTo(enc ObjectEncoder) {
- var err error
-
- switch f.Type {
- case ArrayMarshalerType:
- err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler))
- case ObjectMarshalerType:
- err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler))
- case InlineMarshalerType:
- err = f.Interface.(ObjectMarshaler).MarshalLogObject(enc)
- case BinaryType:
- enc.AddBinary(f.Key, f.Interface.([]byte))
- case BoolType:
- enc.AddBool(f.Key, f.Integer == 1)
- case ByteStringType:
- enc.AddByteString(f.Key, f.Interface.([]byte))
- case Complex128Type:
- enc.AddComplex128(f.Key, f.Interface.(complex128))
- case Complex64Type:
- enc.AddComplex64(f.Key, f.Interface.(complex64))
- case DurationType:
- enc.AddDuration(f.Key, time.Duration(f.Integer))
- case Float64Type:
- enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer)))
- case Float32Type:
- enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer)))
- case Int64Type:
- enc.AddInt64(f.Key, f.Integer)
- case Int32Type:
- enc.AddInt32(f.Key, int32(f.Integer))
- case Int16Type:
- enc.AddInt16(f.Key, int16(f.Integer))
- case Int8Type:
- enc.AddInt8(f.Key, int8(f.Integer))
- case StringType:
- enc.AddString(f.Key, f.String)
- case TimeType:
- if f.Interface != nil {
- enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location)))
- } else {
- // Fall back to UTC if location is nil.
- enc.AddTime(f.Key, time.Unix(0, f.Integer))
- }
- case TimeFullType:
- enc.AddTime(f.Key, f.Interface.(time.Time))
- case Uint64Type:
- enc.AddUint64(f.Key, uint64(f.Integer))
- case Uint32Type:
- enc.AddUint32(f.Key, uint32(f.Integer))
- case Uint16Type:
- enc.AddUint16(f.Key, uint16(f.Integer))
- case Uint8Type:
- enc.AddUint8(f.Key, uint8(f.Integer))
- case UintptrType:
- enc.AddUintptr(f.Key, uintptr(f.Integer))
- case ReflectType:
- err = enc.AddReflected(f.Key, f.Interface)
- case NamespaceType:
- enc.OpenNamespace(f.Key)
- case StringerType:
- err = encodeStringer(f.Key, f.Interface, enc)
- case ErrorType:
- err = encodeError(f.Key, f.Interface.(error), enc)
- case SkipType:
- break
- default:
- panic(fmt.Sprintf("unknown field type: %v", f))
- }
-
- if err != nil {
- enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error())
- }
-}
-
-// Equals returns whether two fields are equal. For non-primitive types such as
-// errors, marshalers, or reflect types, it uses reflect.DeepEqual.
-func (f Field) Equals(other Field) bool {
- if f.Type != other.Type {
- return false
- }
- if f.Key != other.Key {
- return false
- }
-
- switch f.Type {
- case BinaryType, ByteStringType:
- return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte))
- case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType:
- return reflect.DeepEqual(f.Interface, other.Interface)
- default:
- return f == other
- }
-}
-
-func addFields(enc ObjectEncoder, fields []Field) {
- for i := range fields {
- fields[i].AddTo(enc)
- }
-}
-
-func encodeStringer(key string, stringer interface{}, enc ObjectEncoder) (retErr error) {
- // Try to capture panics (from nil references or otherwise) when calling
- // the String() method, similar to https://golang.org/src/fmt/print.go#L540
- defer func() {
- if err := recover(); err != nil {
- // If it's a nil pointer, just say "". The likeliest causes are a
- // Stringer that fails to guard against nil or a nil pointer for a
- // value receiver, and in either case, "" is a nice result.
- if v := reflect.ValueOf(stringer); v.Kind() == reflect.Ptr && v.IsNil() {
- enc.AddString(key, "")
- return
- }
-
- retErr = fmt.Errorf("PANIC=%v", err)
- }
- }()
-
- enc.AddString(key, stringer.(fmt.Stringer).String())
- return nil
-}
diff --git a/vendor/go.uber.org/zap/zapcore/hook.go b/vendor/go.uber.org/zap/zapcore/hook.go
deleted file mode 100644
index 5db4afb302..0000000000
--- a/vendor/go.uber.org/zap/zapcore/hook.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import "go.uber.org/multierr"
-
-type hooked struct {
- Core
- funcs []func(Entry) error
-}
-
-// RegisterHooks wraps a Core and runs a collection of user-defined callback
-// hooks each time a message is logged. Execution of the callbacks is blocking.
-//
-// This offers users an easy way to register simple callbacks (e.g., metrics
-// collection) without implementing the full Core interface.
-func RegisterHooks(core Core, hooks ...func(Entry) error) Core {
- funcs := append([]func(Entry) error{}, hooks...)
- return &hooked{
- Core: core,
- funcs: funcs,
- }
-}
-
-func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
- // Let the wrapped Core decide whether to log this message or not. This
- // also gives the downstream a chance to register itself directly with the
- // CheckedEntry.
- if downstream := h.Core.Check(ent, ce); downstream != nil {
- return downstream.AddCore(ent, h)
- }
- return ce
-}
-
-func (h *hooked) With(fields []Field) Core {
- return &hooked{
- Core: h.Core.With(fields),
- funcs: h.funcs,
- }
-}
-
-func (h *hooked) Write(ent Entry, _ []Field) error {
- // Since our downstream had a chance to register itself directly with the
- // CheckedMessage, we don't need to call it here.
- var err error
- for i := range h.funcs {
- err = multierr.Append(err, h.funcs[i](ent))
- }
- return err
-}
diff --git a/vendor/go.uber.org/zap/zapcore/increase_level.go b/vendor/go.uber.org/zap/zapcore/increase_level.go
deleted file mode 100644
index 5a1749261a..0000000000
--- a/vendor/go.uber.org/zap/zapcore/increase_level.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2020 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import "fmt"
-
-type levelFilterCore struct {
- core Core
- level LevelEnabler
-}
-
-// NewIncreaseLevelCore creates a core that can be used to increase the level of
-// an existing Core. It cannot be used to decrease the logging level, as it acts
-// as a filter before calling the underlying core. If level decreases the log level,
-// an error is returned.
-func NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error) {
- for l := _maxLevel; l >= _minLevel; l-- {
- if !core.Enabled(l) && level.Enabled(l) {
- return nil, fmt.Errorf("invalid increase level, as level %q is allowed by increased level, but not by existing core", l)
- }
- }
-
- return &levelFilterCore{core, level}, nil
-}
-
-func (c *levelFilterCore) Enabled(lvl Level) bool {
- return c.level.Enabled(lvl)
-}
-
-func (c *levelFilterCore) With(fields []Field) Core {
- return &levelFilterCore{c.core.With(fields), c.level}
-}
-
-func (c *levelFilterCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
- if !c.Enabled(ent.Level) {
- return ce
- }
-
- return c.core.Check(ent, ce)
-}
-
-func (c *levelFilterCore) Write(ent Entry, fields []Field) error {
- return c.core.Write(ent, fields)
-}
-
-func (c *levelFilterCore) Sync() error {
- return c.core.Sync()
-}
diff --git a/vendor/go.uber.org/zap/zapcore/json_encoder.go b/vendor/go.uber.org/zap/zapcore/json_encoder.go
deleted file mode 100644
index 5cf7d917e9..0000000000
--- a/vendor/go.uber.org/zap/zapcore/json_encoder.go
+++ /dev/null
@@ -1,534 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "encoding/base64"
- "encoding/json"
- "math"
- "sync"
- "time"
- "unicode/utf8"
-
- "go.uber.org/zap/buffer"
- "go.uber.org/zap/internal/bufferpool"
-)
-
-// For JSON-escaping; see jsonEncoder.safeAddString below.
-const _hex = "0123456789abcdef"
-
-var _jsonPool = sync.Pool{New: func() interface{} {
- return &jsonEncoder{}
-}}
-
-func getJSONEncoder() *jsonEncoder {
- return _jsonPool.Get().(*jsonEncoder)
-}
-
-func putJSONEncoder(enc *jsonEncoder) {
- if enc.reflectBuf != nil {
- enc.reflectBuf.Free()
- }
- enc.EncoderConfig = nil
- enc.buf = nil
- enc.spaced = false
- enc.openNamespaces = 0
- enc.reflectBuf = nil
- enc.reflectEnc = nil
- _jsonPool.Put(enc)
-}
-
-type jsonEncoder struct {
- *EncoderConfig
- buf *buffer.Buffer
- spaced bool // include spaces after colons and commas
- openNamespaces int
-
- // for encoding generic values by reflection
- reflectBuf *buffer.Buffer
- reflectEnc *json.Encoder
-}
-
-// NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder
-// appropriately escapes all field keys and values.
-//
-// Note that the encoder doesn't deduplicate keys, so it's possible to produce
-// a message like
-// {"foo":"bar","foo":"baz"}
-// This is permitted by the JSON specification, but not encouraged. Many
-// libraries will ignore duplicate key-value pairs (typically keeping the last
-// pair) when unmarshaling, but users should attempt to avoid adding duplicate
-// keys.
-func NewJSONEncoder(cfg EncoderConfig) Encoder {
- return newJSONEncoder(cfg, false)
-}
-
-func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
- return &jsonEncoder{
- EncoderConfig: &cfg,
- buf: bufferpool.Get(),
- spaced: spaced,
- }
-}
-
-func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error {
- enc.addKey(key)
- return enc.AppendArray(arr)
-}
-
-func (enc *jsonEncoder) AddObject(key string, obj ObjectMarshaler) error {
- enc.addKey(key)
- return enc.AppendObject(obj)
-}
-
-func (enc *jsonEncoder) AddBinary(key string, val []byte) {
- enc.AddString(key, base64.StdEncoding.EncodeToString(val))
-}
-
-func (enc *jsonEncoder) AddByteString(key string, val []byte) {
- enc.addKey(key)
- enc.AppendByteString(val)
-}
-
-func (enc *jsonEncoder) AddBool(key string, val bool) {
- enc.addKey(key)
- enc.AppendBool(val)
-}
-
-func (enc *jsonEncoder) AddComplex128(key string, val complex128) {
- enc.addKey(key)
- enc.AppendComplex128(val)
-}
-
-func (enc *jsonEncoder) AddDuration(key string, val time.Duration) {
- enc.addKey(key)
- enc.AppendDuration(val)
-}
-
-func (enc *jsonEncoder) AddFloat64(key string, val float64) {
- enc.addKey(key)
- enc.AppendFloat64(val)
-}
-
-func (enc *jsonEncoder) AddInt64(key string, val int64) {
- enc.addKey(key)
- enc.AppendInt64(val)
-}
-
-func (enc *jsonEncoder) resetReflectBuf() {
- if enc.reflectBuf == nil {
- enc.reflectBuf = bufferpool.Get()
- enc.reflectEnc = json.NewEncoder(enc.reflectBuf)
-
- // For consistency with our custom JSON encoder.
- enc.reflectEnc.SetEscapeHTML(false)
- } else {
- enc.reflectBuf.Reset()
- }
-}
-
-var nullLiteralBytes = []byte("null")
-
-// Only invoke the standard JSON encoder if there is actually something to
-// encode; otherwise write JSON null literal directly.
-func (enc *jsonEncoder) encodeReflected(obj interface{}) ([]byte, error) {
- if obj == nil {
- return nullLiteralBytes, nil
- }
- enc.resetReflectBuf()
- if err := enc.reflectEnc.Encode(obj); err != nil {
- return nil, err
- }
- enc.reflectBuf.TrimNewline()
- return enc.reflectBuf.Bytes(), nil
-}
-
-func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error {
- valueBytes, err := enc.encodeReflected(obj)
- if err != nil {
- return err
- }
- enc.addKey(key)
- _, err = enc.buf.Write(valueBytes)
- return err
-}
-
-func (enc *jsonEncoder) OpenNamespace(key string) {
- enc.addKey(key)
- enc.buf.AppendByte('{')
- enc.openNamespaces++
-}
-
-func (enc *jsonEncoder) AddString(key, val string) {
- enc.addKey(key)
- enc.AppendString(val)
-}
-
-func (enc *jsonEncoder) AddTime(key string, val time.Time) {
- enc.addKey(key)
- enc.AppendTime(val)
-}
-
-func (enc *jsonEncoder) AddUint64(key string, val uint64) {
- enc.addKey(key)
- enc.AppendUint64(val)
-}
-
-func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error {
- enc.addElementSeparator()
- enc.buf.AppendByte('[')
- err := arr.MarshalLogArray(enc)
- enc.buf.AppendByte(']')
- return err
-}
-
-func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error {
- enc.addElementSeparator()
- enc.buf.AppendByte('{')
- err := obj.MarshalLogObject(enc)
- enc.buf.AppendByte('}')
- return err
-}
-
-func (enc *jsonEncoder) AppendBool(val bool) {
- enc.addElementSeparator()
- enc.buf.AppendBool(val)
-}
-
-func (enc *jsonEncoder) AppendByteString(val []byte) {
- enc.addElementSeparator()
- enc.buf.AppendByte('"')
- enc.safeAddByteString(val)
- enc.buf.AppendByte('"')
-}
-
-func (enc *jsonEncoder) AppendComplex128(val complex128) {
- enc.addElementSeparator()
- // Cast to a platform-independent, fixed-size type.
- r, i := float64(real(val)), float64(imag(val))
- enc.buf.AppendByte('"')
- // Because we're always in a quoted string, we can use strconv without
- // special-casing NaN and +/-Inf.
- enc.buf.AppendFloat(r, 64)
- enc.buf.AppendByte('+')
- enc.buf.AppendFloat(i, 64)
- enc.buf.AppendByte('i')
- enc.buf.AppendByte('"')
-}
-
-func (enc *jsonEncoder) AppendDuration(val time.Duration) {
- cur := enc.buf.Len()
- if e := enc.EncodeDuration; e != nil {
- e(val, enc)
- }
- if cur == enc.buf.Len() {
- // User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep
- // JSON valid.
- enc.AppendInt64(int64(val))
- }
-}
-
-func (enc *jsonEncoder) AppendInt64(val int64) {
- enc.addElementSeparator()
- enc.buf.AppendInt(val)
-}
-
-func (enc *jsonEncoder) AppendReflected(val interface{}) error {
- valueBytes, err := enc.encodeReflected(val)
- if err != nil {
- return err
- }
- enc.addElementSeparator()
- _, err = enc.buf.Write(valueBytes)
- return err
-}
-
-func (enc *jsonEncoder) AppendString(val string) {
- enc.addElementSeparator()
- enc.buf.AppendByte('"')
- enc.safeAddString(val)
- enc.buf.AppendByte('"')
-}
-
-func (enc *jsonEncoder) AppendTimeLayout(time time.Time, layout string) {
- enc.addElementSeparator()
- enc.buf.AppendByte('"')
- enc.buf.AppendTime(time, layout)
- enc.buf.AppendByte('"')
-}
-
-func (enc *jsonEncoder) AppendTime(val time.Time) {
- cur := enc.buf.Len()
- if e := enc.EncodeTime; e != nil {
- e(val, enc)
- }
- if cur == enc.buf.Len() {
- // User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep
- // output JSON valid.
- enc.AppendInt64(val.UnixNano())
- }
-}
-
-func (enc *jsonEncoder) AppendUint64(val uint64) {
- enc.addElementSeparator()
- enc.buf.AppendUint(val)
-}
-
-func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
-func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) }
-func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) }
-func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) }
-func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) }
-func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) }
-
-func (enc *jsonEncoder) Clone() Encoder {
- clone := enc.clone()
- clone.buf.Write(enc.buf.Bytes())
- return clone
-}
-
-func (enc *jsonEncoder) clone() *jsonEncoder {
- clone := getJSONEncoder()
- clone.EncoderConfig = enc.EncoderConfig
- clone.spaced = enc.spaced
- clone.openNamespaces = enc.openNamespaces
- clone.buf = bufferpool.Get()
- return clone
-}
-
-func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) {
- final := enc.clone()
- final.buf.AppendByte('{')
-
- if final.LevelKey != "" {
- final.addKey(final.LevelKey)
- cur := final.buf.Len()
- final.EncodeLevel(ent.Level, final)
- if cur == final.buf.Len() {
- // User-supplied EncodeLevel was a no-op. Fall back to strings to keep
- // output JSON valid.
- final.AppendString(ent.Level.String())
- }
- }
- if final.TimeKey != "" {
- final.AddTime(final.TimeKey, ent.Time)
- }
- if ent.LoggerName != "" && final.NameKey != "" {
- final.addKey(final.NameKey)
- cur := final.buf.Len()
- nameEncoder := final.EncodeName
-
- // if no name encoder provided, fall back to FullNameEncoder for backwards
- // compatibility
- if nameEncoder == nil {
- nameEncoder = FullNameEncoder
- }
-
- nameEncoder(ent.LoggerName, final)
- if cur == final.buf.Len() {
- // User-supplied EncodeName was a no-op. Fall back to strings to
- // keep output JSON valid.
- final.AppendString(ent.LoggerName)
- }
- }
- if ent.Caller.Defined {
- if final.CallerKey != "" {
- final.addKey(final.CallerKey)
- cur := final.buf.Len()
- final.EncodeCaller(ent.Caller, final)
- if cur == final.buf.Len() {
- // User-supplied EncodeCaller was a no-op. Fall back to strings to
- // keep output JSON valid.
- final.AppendString(ent.Caller.String())
- }
- }
- if final.FunctionKey != "" {
- final.addKey(final.FunctionKey)
- final.AppendString(ent.Caller.Function)
- }
- }
- if final.MessageKey != "" {
- final.addKey(enc.MessageKey)
- final.AppendString(ent.Message)
- }
- if enc.buf.Len() > 0 {
- final.addElementSeparator()
- final.buf.Write(enc.buf.Bytes())
- }
- addFields(final, fields)
- final.closeOpenNamespaces()
- if ent.Stack != "" && final.StacktraceKey != "" {
- final.AddString(final.StacktraceKey, ent.Stack)
- }
- final.buf.AppendByte('}')
- if final.LineEnding != "" {
- final.buf.AppendString(final.LineEnding)
- } else {
- final.buf.AppendString(DefaultLineEnding)
- }
-
- ret := final.buf
- putJSONEncoder(final)
- return ret, nil
-}
-
-func (enc *jsonEncoder) truncate() {
- enc.buf.Reset()
-}
-
-func (enc *jsonEncoder) closeOpenNamespaces() {
- for i := 0; i < enc.openNamespaces; i++ {
- enc.buf.AppendByte('}')
- }
-}
-
-func (enc *jsonEncoder) addKey(key string) {
- enc.addElementSeparator()
- enc.buf.AppendByte('"')
- enc.safeAddString(key)
- enc.buf.AppendByte('"')
- enc.buf.AppendByte(':')
- if enc.spaced {
- enc.buf.AppendByte(' ')
- }
-}
-
-func (enc *jsonEncoder) addElementSeparator() {
- last := enc.buf.Len() - 1
- if last < 0 {
- return
- }
- switch enc.buf.Bytes()[last] {
- case '{', '[', ':', ',', ' ':
- return
- default:
- enc.buf.AppendByte(',')
- if enc.spaced {
- enc.buf.AppendByte(' ')
- }
- }
-}
-
-func (enc *jsonEncoder) appendFloat(val float64, bitSize int) {
- enc.addElementSeparator()
- switch {
- case math.IsNaN(val):
- enc.buf.AppendString(`"NaN"`)
- case math.IsInf(val, 1):
- enc.buf.AppendString(`"+Inf"`)
- case math.IsInf(val, -1):
- enc.buf.AppendString(`"-Inf"`)
- default:
- enc.buf.AppendFloat(val, bitSize)
- }
-}
-
-// safeAddString JSON-escapes a string and appends it to the internal buffer.
-// Unlike the standard library's encoder, it doesn't attempt to protect the
-// user from browser vulnerabilities or JSONP-related problems.
-func (enc *jsonEncoder) safeAddString(s string) {
- for i := 0; i < len(s); {
- if enc.tryAddRuneSelf(s[i]) {
- i++
- continue
- }
- r, size := utf8.DecodeRuneInString(s[i:])
- if enc.tryAddRuneError(r, size) {
- i++
- continue
- }
- enc.buf.AppendString(s[i : i+size])
- i += size
- }
-}
-
-// safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte.
-func (enc *jsonEncoder) safeAddByteString(s []byte) {
- for i := 0; i < len(s); {
- if enc.tryAddRuneSelf(s[i]) {
- i++
- continue
- }
- r, size := utf8.DecodeRune(s[i:])
- if enc.tryAddRuneError(r, size) {
- i++
- continue
- }
- enc.buf.Write(s[i : i+size])
- i += size
- }
-}
-
-// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte.
-func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool {
- if b >= utf8.RuneSelf {
- return false
- }
- if 0x20 <= b && b != '\\' && b != '"' {
- enc.buf.AppendByte(b)
- return true
- }
- switch b {
- case '\\', '"':
- enc.buf.AppendByte('\\')
- enc.buf.AppendByte(b)
- case '\n':
- enc.buf.AppendByte('\\')
- enc.buf.AppendByte('n')
- case '\r':
- enc.buf.AppendByte('\\')
- enc.buf.AppendByte('r')
- case '\t':
- enc.buf.AppendByte('\\')
- enc.buf.AppendByte('t')
- default:
- // Encode bytes < 0x20, except for the escape sequences above.
- enc.buf.AppendString(`\u00`)
- enc.buf.AppendByte(_hex[b>>4])
- enc.buf.AppendByte(_hex[b&0xF])
- }
- return true
-}
-
-func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool {
- if r == utf8.RuneError && size == 1 {
- enc.buf.AppendString(`\ufffd`)
- return true
- }
- return false
-}
diff --git a/vendor/go.uber.org/zap/zapcore/level.go b/vendor/go.uber.org/zap/zapcore/level.go
deleted file mode 100644
index e575c9f432..0000000000
--- a/vendor/go.uber.org/zap/zapcore/level.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "bytes"
- "errors"
- "fmt"
-)
-
-var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level")
-
-// A Level is a logging priority. Higher levels are more important.
-type Level int8
-
-const (
- // DebugLevel logs are typically voluminous, and are usually disabled in
- // production.
- DebugLevel Level = iota - 1
- // InfoLevel is the default logging priority.
- InfoLevel
- // WarnLevel logs are more important than Info, but don't need individual
- // human review.
- WarnLevel
- // ErrorLevel logs are high-priority. If an application is running smoothly,
- // it shouldn't generate any error-level logs.
- ErrorLevel
- // DPanicLevel logs are particularly important errors. In development the
- // logger panics after writing the message.
- DPanicLevel
- // PanicLevel logs a message, then panics.
- PanicLevel
- // FatalLevel logs a message, then calls os.Exit(1).
- FatalLevel
-
- _minLevel = DebugLevel
- _maxLevel = FatalLevel
-)
-
-// String returns a lower-case ASCII representation of the log level.
-func (l Level) String() string {
- switch l {
- case DebugLevel:
- return "debug"
- case InfoLevel:
- return "info"
- case WarnLevel:
- return "warn"
- case ErrorLevel:
- return "error"
- case DPanicLevel:
- return "dpanic"
- case PanicLevel:
- return "panic"
- case FatalLevel:
- return "fatal"
- default:
- return fmt.Sprintf("Level(%d)", l)
- }
-}
-
-// CapitalString returns an all-caps ASCII representation of the log level.
-func (l Level) CapitalString() string {
- // Printing levels in all-caps is common enough that we should export this
- // functionality.
- switch l {
- case DebugLevel:
- return "DEBUG"
- case InfoLevel:
- return "INFO"
- case WarnLevel:
- return "WARN"
- case ErrorLevel:
- return "ERROR"
- case DPanicLevel:
- return "DPANIC"
- case PanicLevel:
- return "PANIC"
- case FatalLevel:
- return "FATAL"
- default:
- return fmt.Sprintf("LEVEL(%d)", l)
- }
-}
-
-// MarshalText marshals the Level to text. Note that the text representation
-// drops the -Level suffix (see example).
-func (l Level) MarshalText() ([]byte, error) {
- return []byte(l.String()), nil
-}
-
-// UnmarshalText unmarshals text to a level. Like MarshalText, UnmarshalText
-// expects the text representation of a Level to drop the -Level suffix (see
-// example).
-//
-// In particular, this makes it easy to configure logging levels using YAML,
-// TOML, or JSON files.
-func (l *Level) UnmarshalText(text []byte) error {
- if l == nil {
- return errUnmarshalNilLevel
- }
- if !l.unmarshalText(text) && !l.unmarshalText(bytes.ToLower(text)) {
- return fmt.Errorf("unrecognized level: %q", text)
- }
- return nil
-}
-
-func (l *Level) unmarshalText(text []byte) bool {
- switch string(text) {
- case "debug", "DEBUG":
- *l = DebugLevel
- case "info", "INFO", "": // make the zero value useful
- *l = InfoLevel
- case "warn", "WARN":
- *l = WarnLevel
- case "error", "ERROR":
- *l = ErrorLevel
- case "dpanic", "DPANIC":
- *l = DPanicLevel
- case "panic", "PANIC":
- *l = PanicLevel
- case "fatal", "FATAL":
- *l = FatalLevel
- default:
- return false
- }
- return true
-}
-
-// Set sets the level for the flag.Value interface.
-func (l *Level) Set(s string) error {
- return l.UnmarshalText([]byte(s))
-}
-
-// Get gets the level for the flag.Getter interface.
-func (l *Level) Get() interface{} {
- return *l
-}
-
-// Enabled returns true if the given level is at or above this level.
-func (l Level) Enabled(lvl Level) bool {
- return lvl >= l
-}
-
-// LevelEnabler decides whether a given logging level is enabled when logging a
-// message.
-//
-// Enablers are intended to be used to implement deterministic filters;
-// concerns like sampling are better implemented as a Core.
-//
-// Each concrete Level value implements a static LevelEnabler which returns
-// true for itself and all higher logging levels. For example WarnLevel.Enabled()
-// will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and
-// FatalLevel, but return false for InfoLevel and DebugLevel.
-type LevelEnabler interface {
- Enabled(Level) bool
-}
diff --git a/vendor/go.uber.org/zap/zapcore/level_strings.go b/vendor/go.uber.org/zap/zapcore/level_strings.go
deleted file mode 100644
index 7af8dadcb3..0000000000
--- a/vendor/go.uber.org/zap/zapcore/level_strings.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import "go.uber.org/zap/internal/color"
-
-var (
- _levelToColor = map[Level]color.Color{
- DebugLevel: color.Magenta,
- InfoLevel: color.Blue,
- WarnLevel: color.Yellow,
- ErrorLevel: color.Red,
- DPanicLevel: color.Red,
- PanicLevel: color.Red,
- FatalLevel: color.Red,
- }
- _unknownLevelColor = color.Red
-
- _levelToLowercaseColorString = make(map[Level]string, len(_levelToColor))
- _levelToCapitalColorString = make(map[Level]string, len(_levelToColor))
-)
-
-func init() {
- for level, color := range _levelToColor {
- _levelToLowercaseColorString[level] = color.Add(level.String())
- _levelToCapitalColorString[level] = color.Add(level.CapitalString())
- }
-}
diff --git a/vendor/go.uber.org/zap/zapcore/marshaler.go b/vendor/go.uber.org/zap/zapcore/marshaler.go
deleted file mode 100644
index c3c55ba0d9..0000000000
--- a/vendor/go.uber.org/zap/zapcore/marshaler.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-// ObjectMarshaler allows user-defined types to efficiently add themselves to the
-// logging context, and to selectively omit information which shouldn't be
-// included in logs (e.g., passwords).
-//
-// Note: ObjectMarshaler is only used when zap.Object is used or when
-// passed directly to zap.Any. It is not used when reflection-based
-// encoding is used.
-type ObjectMarshaler interface {
- MarshalLogObject(ObjectEncoder) error
-}
-
-// ObjectMarshalerFunc is a type adapter that turns a function into an
-// ObjectMarshaler.
-type ObjectMarshalerFunc func(ObjectEncoder) error
-
-// MarshalLogObject calls the underlying function.
-func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error {
- return f(enc)
-}
-
-// ArrayMarshaler allows user-defined types to efficiently add themselves to the
-// logging context, and to selectively omit information which shouldn't be
-// included in logs (e.g., passwords).
-//
-// Note: ArrayMarshaler is only used when zap.Array is used or when
-// passed directly to zap.Any. It is not used when reflection-based
-// encoding is used.
-type ArrayMarshaler interface {
- MarshalLogArray(ArrayEncoder) error
-}
-
-// ArrayMarshalerFunc is a type adapter that turns a function into an
-// ArrayMarshaler.
-type ArrayMarshalerFunc func(ArrayEncoder) error
-
-// MarshalLogArray calls the underlying function.
-func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error {
- return f(enc)
-}
diff --git a/vendor/go.uber.org/zap/zapcore/memory_encoder.go b/vendor/go.uber.org/zap/zapcore/memory_encoder.go
deleted file mode 100644
index dfead0829d..0000000000
--- a/vendor/go.uber.org/zap/zapcore/memory_encoder.go
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import "time"
-
-// MapObjectEncoder is an ObjectEncoder backed by a simple
-// map[string]interface{}. It's not fast enough for production use, but it's
-// helpful in tests.
-type MapObjectEncoder struct {
- // Fields contains the entire encoded log context.
- Fields map[string]interface{}
- // cur is a pointer to the namespace we're currently writing to.
- cur map[string]interface{}
-}
-
-// NewMapObjectEncoder creates a new map-backed ObjectEncoder.
-func NewMapObjectEncoder() *MapObjectEncoder {
- m := make(map[string]interface{})
- return &MapObjectEncoder{
- Fields: m,
- cur: m,
- }
-}
-
-// AddArray implements ObjectEncoder.
-func (m *MapObjectEncoder) AddArray(key string, v ArrayMarshaler) error {
- arr := &sliceArrayEncoder{elems: make([]interface{}, 0)}
- err := v.MarshalLogArray(arr)
- m.cur[key] = arr.elems
- return err
-}
-
-// AddObject implements ObjectEncoder.
-func (m *MapObjectEncoder) AddObject(k string, v ObjectMarshaler) error {
- newMap := NewMapObjectEncoder()
- m.cur[k] = newMap.Fields
- return v.MarshalLogObject(newMap)
-}
-
-// AddBinary implements ObjectEncoder.
-func (m *MapObjectEncoder) AddBinary(k string, v []byte) { m.cur[k] = v }
-
-// AddByteString implements ObjectEncoder.
-func (m *MapObjectEncoder) AddByteString(k string, v []byte) { m.cur[k] = string(v) }
-
-// AddBool implements ObjectEncoder.
-func (m *MapObjectEncoder) AddBool(k string, v bool) { m.cur[k] = v }
-
-// AddDuration implements ObjectEncoder.
-func (m MapObjectEncoder) AddDuration(k string, v time.Duration) { m.cur[k] = v }
-
-// AddComplex128 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddComplex128(k string, v complex128) { m.cur[k] = v }
-
-// AddComplex64 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddComplex64(k string, v complex64) { m.cur[k] = v }
-
-// AddFloat64 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddFloat64(k string, v float64) { m.cur[k] = v }
-
-// AddFloat32 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddFloat32(k string, v float32) { m.cur[k] = v }
-
-// AddInt implements ObjectEncoder.
-func (m *MapObjectEncoder) AddInt(k string, v int) { m.cur[k] = v }
-
-// AddInt64 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddInt64(k string, v int64) { m.cur[k] = v }
-
-// AddInt32 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddInt32(k string, v int32) { m.cur[k] = v }
-
-// AddInt16 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddInt16(k string, v int16) { m.cur[k] = v }
-
-// AddInt8 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddInt8(k string, v int8) { m.cur[k] = v }
-
-// AddString implements ObjectEncoder.
-func (m *MapObjectEncoder) AddString(k string, v string) { m.cur[k] = v }
-
-// AddTime implements ObjectEncoder.
-func (m MapObjectEncoder) AddTime(k string, v time.Time) { m.cur[k] = v }
-
-// AddUint implements ObjectEncoder.
-func (m *MapObjectEncoder) AddUint(k string, v uint) { m.cur[k] = v }
-
-// AddUint64 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddUint64(k string, v uint64) { m.cur[k] = v }
-
-// AddUint32 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddUint32(k string, v uint32) { m.cur[k] = v }
-
-// AddUint16 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddUint16(k string, v uint16) { m.cur[k] = v }
-
-// AddUint8 implements ObjectEncoder.
-func (m *MapObjectEncoder) AddUint8(k string, v uint8) { m.cur[k] = v }
-
-// AddUintptr implements ObjectEncoder.
-func (m *MapObjectEncoder) AddUintptr(k string, v uintptr) { m.cur[k] = v }
-
-// AddReflected implements ObjectEncoder.
-func (m *MapObjectEncoder) AddReflected(k string, v interface{}) error {
- m.cur[k] = v
- return nil
-}
-
-// OpenNamespace implements ObjectEncoder.
-func (m *MapObjectEncoder) OpenNamespace(k string) {
- ns := make(map[string]interface{})
- m.cur[k] = ns
- m.cur = ns
-}
-
-// sliceArrayEncoder is an ArrayEncoder backed by a simple []interface{}. Like
-// the MapObjectEncoder, it's not designed for production use.
-type sliceArrayEncoder struct {
- elems []interface{}
-}
-
-func (s *sliceArrayEncoder) AppendArray(v ArrayMarshaler) error {
- enc := &sliceArrayEncoder{}
- err := v.MarshalLogArray(enc)
- s.elems = append(s.elems, enc.elems)
- return err
-}
-
-func (s *sliceArrayEncoder) AppendObject(v ObjectMarshaler) error {
- m := NewMapObjectEncoder()
- err := v.MarshalLogObject(m)
- s.elems = append(s.elems, m.Fields)
- return err
-}
-
-func (s *sliceArrayEncoder) AppendReflected(v interface{}) error {
- s.elems = append(s.elems, v)
- return nil
-}
-
-func (s *sliceArrayEncoder) AppendBool(v bool) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems = append(s.elems, string(v)) }
-func (s *sliceArrayEncoder) AppendComplex128(v complex128) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendComplex64(v complex64) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendFloat64(v float64) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendFloat32(v float32) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt(v int) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt64(v int64) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt32(v int32) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt16(v int16) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt8(v int8) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendString(v string) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendTime(v time.Time) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint(v uint) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint64(v uint64) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint32(v uint32) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint16(v uint16) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint8(v uint8) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUintptr(v uintptr) { s.elems = append(s.elems, v) }
diff --git a/vendor/go.uber.org/zap/zapcore/sampler.go b/vendor/go.uber.org/zap/zapcore/sampler.go
deleted file mode 100644
index 25f10ca1d7..0000000000
--- a/vendor/go.uber.org/zap/zapcore/sampler.go
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "time"
-
- "go.uber.org/atomic"
-)
-
-const (
- _numLevels = _maxLevel - _minLevel + 1
- _countersPerLevel = 4096
-)
-
-type counter struct {
- resetAt atomic.Int64
- counter atomic.Uint64
-}
-
-type counters [_numLevels][_countersPerLevel]counter
-
-func newCounters() *counters {
- return &counters{}
-}
-
-func (cs *counters) get(lvl Level, key string) *counter {
- i := lvl - _minLevel
- j := fnv32a(key) % _countersPerLevel
- return &cs[i][j]
-}
-
-// fnv32a, adapted from "hash/fnv", but without a []byte(string) alloc
-func fnv32a(s string) uint32 {
- const (
- offset32 = 2166136261
- prime32 = 16777619
- )
- hash := uint32(offset32)
- for i := 0; i < len(s); i++ {
- hash ^= uint32(s[i])
- hash *= prime32
- }
- return hash
-}
-
-func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 {
- tn := t.UnixNano()
- resetAfter := c.resetAt.Load()
- if resetAfter > tn {
- return c.counter.Inc()
- }
-
- c.counter.Store(1)
-
- newResetAfter := tn + tick.Nanoseconds()
- if !c.resetAt.CAS(resetAfter, newResetAfter) {
- // We raced with another goroutine trying to reset, and it also reset
- // the counter to 1, so we need to reincrement the counter.
- return c.counter.Inc()
- }
-
- return 1
-}
-
-// SamplingDecision is a decision represented as a bit field made by sampler.
-// More decisions may be added in the future.
-type SamplingDecision uint32
-
-const (
- // LogDropped indicates that the Sampler dropped a log entry.
- LogDropped SamplingDecision = 1 << iota
- // LogSampled indicates that the Sampler sampled a log entry.
- LogSampled
-)
-
-// optionFunc wraps a func so it satisfies the SamplerOption interface.
-type optionFunc func(*sampler)
-
-func (f optionFunc) apply(s *sampler) {
- f(s)
-}
-
-// SamplerOption configures a Sampler.
-type SamplerOption interface {
- apply(*sampler)
-}
-
-// nopSamplingHook is the default hook used by sampler.
-func nopSamplingHook(Entry, SamplingDecision) {}
-
-// SamplerHook registers a function which will be called when Sampler makes a
-// decision.
-//
-// This hook may be used to get visibility into the performance of the sampler.
-// For example, use it to track metrics of dropped versus sampled logs.
-//
-// var dropped atomic.Int64
-// zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) {
-// if dec&zapcore.LogDropped > 0 {
-// dropped.Inc()
-// }
-// })
-func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption {
- return optionFunc(func(s *sampler) {
- s.hook = hook
- })
-}
-
-// NewSamplerWithOptions creates a Core that samples incoming entries, which
-// caps the CPU and I/O load of logging while attempting to preserve a
-// representative subset of your logs.
-//
-// Zap samples by logging the first N entries with a given level and message
-// each tick. If more Entries with the same level and message are seen during
-// the same interval, every Mth message is logged and the rest are dropped.
-//
-// Sampler can be configured to report sampling decisions with the SamplerHook
-// option.
-//
-// Keep in mind that zap's sampling implementation is optimized for speed over
-// absolute precision; under load, each tick may be slightly over- or
-// under-sampled.
-func NewSamplerWithOptions(core Core, tick time.Duration, first, thereafter int, opts ...SamplerOption) Core {
- s := &sampler{
- Core: core,
- tick: tick,
- counts: newCounters(),
- first: uint64(first),
- thereafter: uint64(thereafter),
- hook: nopSamplingHook,
- }
- for _, opt := range opts {
- opt.apply(s)
- }
-
- return s
-}
-
-type sampler struct {
- Core
-
- counts *counters
- tick time.Duration
- first, thereafter uint64
- hook func(Entry, SamplingDecision)
-}
-
-// NewSampler creates a Core that samples incoming entries, which
-// caps the CPU and I/O load of logging while attempting to preserve a
-// representative subset of your logs.
-//
-// Zap samples by logging the first N entries with a given level and message
-// each tick. If more Entries with the same level and message are seen during
-// the same interval, every Mth message is logged and the rest are dropped.
-//
-// Keep in mind that zap's sampling implementation is optimized for speed over
-// absolute precision; under load, each tick may be slightly over- or
-// under-sampled.
-//
-// Deprecated: use NewSamplerWithOptions.
-func NewSampler(core Core, tick time.Duration, first, thereafter int) Core {
- return NewSamplerWithOptions(core, tick, first, thereafter)
-}
-
-func (s *sampler) With(fields []Field) Core {
- return &sampler{
- Core: s.Core.With(fields),
- tick: s.tick,
- counts: s.counts,
- first: s.first,
- thereafter: s.thereafter,
- hook: s.hook,
- }
-}
-
-func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
- if !s.Enabled(ent.Level) {
- return ce
- }
-
- counter := s.counts.get(ent.Level, ent.Message)
- n := counter.IncCheckReset(ent.Time, s.tick)
- if n > s.first && (n-s.first)%s.thereafter != 0 {
- s.hook(ent, LogDropped)
- return ce
- }
- s.hook(ent, LogSampled)
- return s.Core.Check(ent, ce)
-}
diff --git a/vendor/go.uber.org/zap/zapcore/tee.go b/vendor/go.uber.org/zap/zapcore/tee.go
deleted file mode 100644
index 07a32eef9a..0000000000
--- a/vendor/go.uber.org/zap/zapcore/tee.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import "go.uber.org/multierr"
-
-type multiCore []Core
-
-// NewTee creates a Core that duplicates log entries into two or more
-// underlying Cores.
-//
-// Calling it with a single Core returns the input unchanged, and calling
-// it with no input returns a no-op Core.
-func NewTee(cores ...Core) Core {
- switch len(cores) {
- case 0:
- return NewNopCore()
- case 1:
- return cores[0]
- default:
- return multiCore(cores)
- }
-}
-
-func (mc multiCore) With(fields []Field) Core {
- clone := make(multiCore, len(mc))
- for i := range mc {
- clone[i] = mc[i].With(fields)
- }
- return clone
-}
-
-func (mc multiCore) Enabled(lvl Level) bool {
- for i := range mc {
- if mc[i].Enabled(lvl) {
- return true
- }
- }
- return false
-}
-
-func (mc multiCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
- for i := range mc {
- ce = mc[i].Check(ent, ce)
- }
- return ce
-}
-
-func (mc multiCore) Write(ent Entry, fields []Field) error {
- var err error
- for i := range mc {
- err = multierr.Append(err, mc[i].Write(ent, fields))
- }
- return err
-}
-
-func (mc multiCore) Sync() error {
- var err error
- for i := range mc {
- err = multierr.Append(err, mc[i].Sync())
- }
- return err
-}
diff --git a/vendor/go.uber.org/zap/zapcore/write_syncer.go b/vendor/go.uber.org/zap/zapcore/write_syncer.go
deleted file mode 100644
index d4a1af3d07..0000000000
--- a/vendor/go.uber.org/zap/zapcore/write_syncer.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package zapcore
-
-import (
- "io"
- "sync"
-
- "go.uber.org/multierr"
-)
-
-// A WriteSyncer is an io.Writer that can also flush any buffered data. Note
-// that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer.
-type WriteSyncer interface {
- io.Writer
- Sync() error
-}
-
-// AddSync converts an io.Writer to a WriteSyncer. It attempts to be
-// intelligent: if the concrete type of the io.Writer implements WriteSyncer,
-// we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync.
-func AddSync(w io.Writer) WriteSyncer {
- switch w := w.(type) {
- case WriteSyncer:
- return w
- default:
- return writerWrapper{w}
- }
-}
-
-type lockedWriteSyncer struct {
- sync.Mutex
- ws WriteSyncer
-}
-
-// Lock wraps a WriteSyncer in a mutex to make it safe for concurrent use. In
-// particular, *os.Files must be locked before use.
-func Lock(ws WriteSyncer) WriteSyncer {
- if _, ok := ws.(*lockedWriteSyncer); ok {
- // no need to layer on another lock
- return ws
- }
- return &lockedWriteSyncer{ws: ws}
-}
-
-func (s *lockedWriteSyncer) Write(bs []byte) (int, error) {
- s.Lock()
- n, err := s.ws.Write(bs)
- s.Unlock()
- return n, err
-}
-
-func (s *lockedWriteSyncer) Sync() error {
- s.Lock()
- err := s.ws.Sync()
- s.Unlock()
- return err
-}
-
-type writerWrapper struct {
- io.Writer
-}
-
-func (w writerWrapper) Sync() error {
- return nil
-}
-
-type multiWriteSyncer []WriteSyncer
-
-// NewMultiWriteSyncer creates a WriteSyncer that duplicates its writes
-// and sync calls, much like io.MultiWriter.
-func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncer {
- if len(ws) == 1 {
- return ws[0]
- }
- return multiWriteSyncer(ws)
-}
-
-// See https://golang.org/src/io/multi.go
-// When not all underlying syncers write the same number of bytes,
-// the smallest number is returned even though Write() is called on
-// all of them.
-func (ws multiWriteSyncer) Write(p []byte) (int, error) {
- var writeErr error
- nWritten := 0
- for _, w := range ws {
- n, err := w.Write(p)
- writeErr = multierr.Append(writeErr, err)
- if nWritten == 0 && n != 0 {
- nWritten = n
- } else if n < nWritten {
- nWritten = n
- }
- }
- return nWritten, writeErr
-}
-
-func (ws multiWriteSyncer) Sync() error {
- var err error
- for _, w := range ws {
- err = multierr.Append(err, w.Sync())
- }
- return err
-}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index b5617c2ef1..1100dd960a 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -398,9 +398,12 @@ github.com/mattermost/gziphandler
github.com/mattermost/ldap
# github.com/mattermost/logr v1.0.13
## explicit
-github.com/mattermost/logr
-github.com/mattermost/logr/format
-github.com/mattermost/logr/target
+# github.com/mattermost/logr/v2 v2.0.10
+## explicit
+github.com/mattermost/logr/v2
+github.com/mattermost/logr/v2/config
+github.com/mattermost/logr/v2/formatters
+github.com/mattermost/logr/v2/targets
# github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0
## explicit
github.com/mattermost/rsc/gf256
@@ -681,10 +684,6 @@ github.com/vmihailenco/msgpack/v5/msgpcode
github.com/vmihailenco/tagparser/v2
github.com/vmihailenco/tagparser/v2/internal
github.com/vmihailenco/tagparser/v2/internal/parser
-# github.com/wiggin77/cfg v1.0.2
-github.com/wiggin77/cfg
-github.com/wiggin77/cfg/ini
-github.com/wiggin77/cfg/timeconv
# github.com/wiggin77/merror v1.0.3
## explicit
github.com/wiggin77/merror
@@ -730,15 +729,8 @@ go.opentelemetry.io/otel/metric/unit
go.uber.org/atomic
# go.uber.org/multierr v1.7.0
## explicit
-go.uber.org/multierr
# go.uber.org/zap v1.17.0
## explicit
-go.uber.org/zap
-go.uber.org/zap/buffer
-go.uber.org/zap/internal/bufferpool
-go.uber.org/zap/internal/color
-go.uber.org/zap/internal/exit
-go.uber.org/zap/zapcore
# golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
## explicit
golang.org/x/crypto/acme
diff --git a/web/context.go b/web/context.go
index 3cca15b0e2..f2c6d9882c 100644
--- a/web/context.go
+++ b/web/context.go
@@ -35,7 +35,7 @@ func (c *Context) LogAuditRec(rec *audit.Record) {
// LogAuditRec logs an audit record using specified Level.
// If the context is flagged with a permissions error then `level`
// is ignored and the audit record is emitted with `LevelPerms`.
-func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel) {
+func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level mlog.Level) {
if rec == nil {
return
}
diff --git a/web/main_test.go b/web/main_test.go
index eebef55cc7..1099e210a0 100644
--- a/web/main_test.go
+++ b/web/main_test.go
@@ -6,7 +6,6 @@ package web
import (
"testing"
- "github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/testlib"
)
@@ -18,8 +17,6 @@ func TestMain(m *testing.M) {
EnableResources: true,
}
- mlog.DisableZap()
-
mainHelper = testlib.NewMainHelperWithOptions(&options)
defer mainHelper.Close()
diff --git a/web/oauth_test.go b/web/oauth_test.go
index 9627b228e9..ab4266bcc0 100644
--- a/web/oauth_test.go
+++ b/web/oauth_test.go
@@ -379,8 +379,7 @@ func TestMobileLoginWithOAuth(t *testing.T) {
translationFunc := i18n.GetUserTranslations("en")
c.AppContext.SetT(translationFunc)
- buffer := &bytes.Buffer{}
- c.Logger = mlog.NewTestingLogger(t, buffer)
+ c.Logger = th.TestLogger
provider := &MattermostTestProvider{}
einterfaces.RegisterOAuthProvider(model.ServiceGitlab, provider)
@@ -583,7 +582,8 @@ func TestOAuthComplete_ErrorMessages(t *testing.T) {
translationFunc := i18n.GetUserTranslations("en")
c.AppContext.SetT(translationFunc)
buffer := &bytes.Buffer{}
- c.Logger = mlog.NewTestingLogger(t, buffer)
+ c.Logger = mlog.CreateTestLogger(t, buffer, mlog.StdAll...)
+ defer c.Logger.Shutdown()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Enable = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
provider := &MattermostTestProvider{}
@@ -712,8 +712,6 @@ func (th *TestHelper) Logout(client *model.Client4) {
}
func (th *TestHelper) SaveDefaultRolePermissions() map[string][]string {
- utils.DisableDebugLogForTest()
-
results := make(map[string][]string)
for _, roleName := range []string{
@@ -726,24 +724,18 @@ func (th *TestHelper) SaveDefaultRolePermissions() map[string][]string {
} {
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
results[roleName] = role.Permissions
}
-
- utils.EnableDebugLogForTest()
return results
}
func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
- utils.DisableDebugLogForTest()
-
for roleName, permissions := range data {
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
@@ -755,12 +747,9 @@ func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
}
-
- utils.EnableDebugLogForTest()
}
// func (th *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
@@ -796,17 +785,13 @@ func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
// }
func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
- utils.DisableDebugLogForTest()
-
role, err1 := th.App.GetRoleByName(context.Background(), roleName)
if err1 != nil {
- utils.EnableDebugLogForTest()
panic(err1)
}
for _, existingPermission := range role.Permissions {
if existingPermission == permission {
- utils.EnableDebugLogForTest()
return
}
}
@@ -815,9 +800,6 @@ func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
- utils.EnableDebugLogForTest()
panic(err2)
}
-
- utils.EnableDebugLogForTest()
}
diff --git a/web/web_test.go b/web/web_test.go
index 214a31b9ff..8041c4cbf2 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -45,6 +45,8 @@ type TestHelper struct {
tempWorkspace string
IncludeCacheLayer bool
+
+ TestLogger *mlog.Logger
}
func SetupWithStoreMock(tb testing.TB) *TestHelper {
@@ -52,7 +54,7 @@ func SetupWithStoreMock(tb testing.TB) *TestHelper {
tb.SkipNow()
}
- th := setupTestHelper(false)
+ th := setupTestHelper(tb, false)
emptyMockStore := mocks.Store{}
emptyMockStore.On("Close").Return(nil)
th.App.Srv().Store = &emptyMockStore
@@ -65,10 +67,10 @@ func Setup(tb testing.TB) *TestHelper {
}
store := mainHelper.GetStore()
store.DropAllTables()
- return setupTestHelper(true)
+ return setupTestHelper(tb, true)
}
-func setupTestHelper(includeCacheLayer bool) *TestHelper {
+func setupTestHelper(tb testing.TB, includeCacheLayer bool) *TestHelper {
memoryStore := config.NewTestMemoryStore()
newConfig := memoryStore.Get().Clone()
*newConfig.AnnouncementSettings.AdminNoticesEnabled = false
@@ -79,7 +81,14 @@ func setupTestHelper(includeCacheLayer bool) *TestHelper {
options = append(options, app.ConfigStore(memoryStore))
options = append(options, app.StoreOverride(mainHelper.Store))
- mlog.DisableZap()
+ testLogger, _ := mlog.NewLogger()
+ logCfg, _ := config.MloggerConfigFromLoggerConfig(&newConfig.LogSettings, nil, config.GetLogFileLocation)
+ if errCfg := testLogger.ConfigureTargets(logCfg); errCfg != nil {
+ panic("failed to configure test logger: " + errCfg.Error())
+ }
+ // lock logger config so server init cannot override it during testing.
+ testLogger.LockConfiguration()
+ options = append(options, app.SetLogger(testLogger))
s, err := app.NewServer(options...)
if err != nil {
@@ -129,6 +138,7 @@ func setupTestHelper(includeCacheLayer bool) *TestHelper {
Server: s,
Web: web,
IncludeCacheLayer: includeCacheLayer,
+ TestLogger: testLogger,
}
return th