diff --git a/contracts/log/log.go b/contracts/log/log.go index b22e72ed9..bb80f3005 100644 --- a/contracts/log/log.go +++ b/contracts/log/log.go @@ -23,6 +23,8 @@ const ( DebugLevel ) +type Data map[string]any + type Log interface { // WithContext adds a context to the logger. WithContext(ctx context.Context) Writer @@ -96,28 +98,30 @@ type Hook interface { } type Entry interface { + // Code returns the associated code. + Code() string // Context returns the context of the entry. Context() context.Context + // Data returns the data of the entry. + Data() Data // Level returns the level of the entry. Level() Level - // Time returns the timestamp of the entry. - Time() time.Time // Message returns the message of the entry. Message() string - // Code returns the associated code. - Code() string - // With returns additional context data. - With() map[string]any - // User returns the user information. - User() any - // Tags returns the list of tags. - Tags() []string // Owner returns the log's owner. Owner() any // Request returns the request data. Request() map[string]any // Response returns the response data. Response() map[string]any + // Tags returns the list of tags. + Tags() []string + // Time returns the timestamp of the entry. + Time() time.Time // Trace returns the stack trace or trace data. Trace() map[string]any + // User returns the user information. + User() any + // With returns additional context data. + With() map[string]any } diff --git a/log/application.go b/log/application.go index ed3994cf8..ecb6b75b9 100644 --- a/log/application.go +++ b/log/application.go @@ -19,9 +19,7 @@ type Application struct { } func NewApplication(config config.Config, json foundation.Json) (*Application, error) { - instance := logrus.New() - instance.SetLevel(logrus.DebugLevel) - + instance := NewLogrus() if config != nil { if channel := config.GetString("logging.default"); channel != "" { if err := registerHook(config, json, instance, channel); err != nil { @@ -47,9 +45,7 @@ func (r *Application) Channel(channel string) log.Writer { return r.Writer } - instance := logrus.New() - instance.SetLevel(logrus.DebugLevel) - + instance := NewLogrus() if err := registerHook(r.config, r.json, instance, channel); err != nil { color.Errorln(err) return nil @@ -63,9 +59,7 @@ func (r *Application) Stack(channels []string) log.Writer { return r.Writer } - instance := logrus.New() - instance.SetLevel(logrus.DebugLevel) - + instance := NewLogrus() for _, channel := range channels { if channel == "" { continue diff --git a/log/entry.go b/log/entry.go index f5c927c0e..0cc0ffbce 100644 --- a/log/entry.go +++ b/log/entry.go @@ -9,6 +9,7 @@ import ( type Entry struct { ctx context.Context + data log.Data level log.Level time time.Time message string @@ -22,50 +23,54 @@ type Entry struct { stacktrace map[string]any } +func (r *Entry) Code() string { + return r.code +} + func (r *Entry) Context() context.Context { return r.ctx } -func (r *Entry) Level() log.Level { - return r.level +func (r *Entry) Data() log.Data { + return r.data } -func (r *Entry) Time() time.Time { - return r.time +func (r *Entry) Level() log.Level { + return r.level } func (r *Entry) Message() string { return r.message } -func (r *Entry) Code() string { - return r.code +func (r *Entry) Owner() any { + return r.owner } -func (r *Entry) With() map[string]any { - return r.with +func (r *Entry) Request() map[string]any { + return r.request } -func (r *Entry) User() any { - return r.user +func (r *Entry) Response() map[string]any { + return r.response } func (r *Entry) Tags() []string { return r.tags } -func (r *Entry) Owner() any { - return r.owner +func (r *Entry) Time() time.Time { + return r.time } -func (r *Entry) Request() map[string]any { - return r.request +func (r *Entry) Trace() map[string]any { + return r.stacktrace } -func (r *Entry) Response() map[string]any { - return r.response +func (r *Entry) User() any { + return r.user } -func (r *Entry) Trace() map[string]any { - return r.stacktrace +func (r *Entry) With() map[string]any { + return r.with } diff --git a/log/logrus_writer.go b/log/logrus_writer.go index 2681c2a3a..9924bdcff 100644 --- a/log/logrus_writer.go +++ b/log/logrus_writer.go @@ -3,6 +3,7 @@ package log import ( "fmt" "io" + "os" "github.com/rotisserie/eris" "github.com/sirupsen/logrus" @@ -17,6 +18,14 @@ import ( "github.com/goravel/framework/log/logger" ) +func NewLogrus() *logrus.Logger { + instance := logrus.New() + instance.SetLevel(logrus.DebugLevel) + instance.SetOutput(io.Discard) + + return instance +} + type Writer struct { code string @@ -294,11 +303,14 @@ func (r *Writer) toMap() map[string]any { } func registerHook(config config.Config, json foundation.Json, instance *logrus.Logger, channel string) error { - channelPath := "logging.channels." + channel - driver := config.GetString(channelPath + ".driver") + var ( + hook logrus.Hook + err error + + channelPath = "logging.channels." + channel + driver = config.GetString(channelPath + ".driver") + ) - var hook logrus.Hook - var err error switch driver { case log.StackDriver: for _, stackChannel := range config.Get(channelPath + ".channels").([]string) { @@ -313,25 +325,27 @@ func registerHook(config config.Config, json foundation.Json, instance *logrus.L return nil case log.SingleDriver: - if !config.GetBool(channelPath + ".print") { - instance.SetOutput(io.Discard) - } - logLogger := logger.NewSingle(config, json) hook, err = logLogger.Handle(channelPath) if err != nil { return err } - case log.DailyDriver: - if !config.GetBool(channelPath + ".print") { - instance.SetOutput(io.Discard) - } + if config.GetBool(channelPath + ".print") { + instance.SetOutput(os.Stdout) + instance.SetFormatter(formatter.NewGeneral(config, json)) + } + case log.DailyDriver: logLogger := logger.NewDaily(config, json) hook, err = logLogger.Handle(channelPath) if err != nil { return err } + + if config.GetBool(channelPath + ".print") { + instance.SetOutput(os.Stdout) + instance.SetFormatter(formatter.NewGeneral(config, json)) + } case log.CustomDriver: logLogger := config.Get(channelPath + ".via").(log.Logger) logHook, err := logLogger.Handle(channelPath) @@ -344,8 +358,6 @@ func registerHook(config config.Config, json foundation.Json, instance *logrus.L return errors.LogDriverNotSupported.Args(channel) } - instance.SetFormatter(formatter.NewGeneral(config, json)) - instance.AddHook(hook) return nil @@ -368,6 +380,7 @@ func (h *Hook) Levels() []logrus.Level { func (h *Hook) Fire(entry *logrus.Entry) error { e := &Entry{ ctx: entry.Context, + data: map[string]any(entry.Data), level: log.Level(entry.Level), time: entry.Time, message: entry.Message, diff --git a/log/logrus_writer_test.go b/log/logrus_writer_test.go index ae4eb0f6c..3ac457d21 100644 --- a/log/logrus_writer_test.go +++ b/log/logrus_writer_test.go @@ -79,8 +79,6 @@ func TestLogrus(t *testing.T) { setup: func() { mockConfig.On("GetString", "logging.channels.daily.level").Return("info").Once() mockConfig.On("GetString", "logging.channels.single.level").Return("info").Once() - mockConfig.On("GetString", "app.timezone").Return("UTC").Once() - mockConfig.On("GetString", "app.env").Return("test").Once() log, err = NewApplication(mockConfig, j) log.Debug("No Debug Goravel") }, diff --git a/mocks/log/Entry.go b/mocks/log/Entry.go index db1f9ee1b..2f63559fe 100644 --- a/mocks/log/Entry.go +++ b/mocks/log/Entry.go @@ -116,6 +116,53 @@ func (_c *Entry_Context_Call) RunAndReturn(run func() context.Context) *Entry_Co return _c } +// Data provides a mock function with given fields: +func (_m *Entry) Data() log.Data { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Data") + } + + var r0 log.Data + if rf, ok := ret.Get(0).(func() log.Data); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(log.Data) + } + } + + return r0 +} + +// Entry_Data_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Data' +type Entry_Data_Call struct { + *mock.Call +} + +// Data is a helper method to define mock.On call +func (_e *Entry_Expecter) Data() *Entry_Data_Call { + return &Entry_Data_Call{Call: _e.mock.On("Data")} +} + +func (_c *Entry_Data_Call) Run(run func()) *Entry_Data_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Entry_Data_Call) Return(_a0 log.Data) *Entry_Data_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Entry_Data_Call) RunAndReturn(run func() log.Data) *Entry_Data_Call { + _c.Call.Return(run) + return _c +} + // Level provides a mock function with given fields: func (_m *Entry) Level() log.Level { ret := _m.Called() diff --git a/support/constant.go b/support/constant.go index b819d6179..58cbaff2c 100644 --- a/support/constant.go +++ b/support/constant.go @@ -1,6 +1,6 @@ package support -const Version string = "v1.14.7" +const Version string = "v1.15.0" const ( EnvRuntime = "runtime"