From 2628202ff167e60adb6646e582f20b3268b55927 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 2 Jan 2024 20:20:02 +0300 Subject: [PATCH] add source with func name --- field/encoder_text.go | 15 ++++++++++-- global.go | 2 +- global_example_test.go | 24 +++++++++++++++++++ logger_example_caller_test.go | 8 +++---- middleware.go | 1 + source.go | 45 +++++++++++++++++++++++++++++++++++ source_example_test.go | 25 +++++++++++++++++++ writter.go | 2 +- 8 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 global_example_test.go create mode 100644 source.go create mode 100644 source_example_test.go diff --git a/field/encoder_text.go b/field/encoder_text.go index 073a157..e3be369 100644 --- a/field/encoder_text.go +++ b/field/encoder_text.go @@ -1,6 +1,7 @@ package field import ( + "encoding" "fmt" ) @@ -8,8 +9,18 @@ func NewEncoderText(opts ...func(*BaseEncoder)) BaseEncoder { opts = append([]func(*BaseEncoder){ WithGropuConfig(0, 0, ' '), WithNullValue(""), - WithDefaultValue(func(dst []byte, _ Encoder, val Value) []byte { - return fmt.Appendf(dst, "%+v", val.Any()) + WithDefaultValue(func(dst []byte, enc Encoder, val Value) []byte { + switch value := val.Any().(type) { + case encoding.TextMarshaler: + data, err := value.MarshalText() + if err != nil { + return enc.AppendValue(dst, ErrorValue(err)) + } + + return enc.AppendValue(dst, StringValue(string(data))) + default: + return fmt.Appendf(dst, "%+v", val.Any()) + } }), }, opts...) diff --git a/global.go b/global.go index b221912..c5c49b5 100644 --- a/global.go +++ b/global.go @@ -10,7 +10,7 @@ import ( //nolint:gochecknoglobals var global = With(New(), - WithCaller(KeySource, 1, false), + WithSource(1), WithLevel(KeyLevel, level.Debug), WithExit(level.Alert), WithPanic(level.Emergency), diff --git a/global_example_test.go b/global_example_test.go new file mode 100644 index 0000000..882f70b --- /dev/null +++ b/global_example_test.go @@ -0,0 +1,24 @@ +package log_test + +import ( + "context" + + "gitoa.ru/go-4devs/log" + "gitoa.ru/go-4devs/log/level" +) + +func ExampleDebug() { + logger := log.With(log.New(log.WithStdout()), + log.WithSource(2), + log.WithLevel(log.KeyLevel, level.Debug), + log.WithExit(level.Alert), + log.WithPanic(level.Emergency), + ) + + log.SetLogger(logger) + + ctx := context.Background() + log.Debug(ctx, "debug message") + // Output: + // msg="debug message" source=global_example_test.go:21 level=debug +} diff --git a/logger_example_caller_test.go b/logger_example_caller_test.go index 3901f08..1b77d0f 100644 --- a/logger_example_caller_test.go +++ b/logger_example_caller_test.go @@ -9,14 +9,14 @@ func ExampleNew_withCaller() { logger := log.With( log.New(log.WithStdout()), log.WithLevel("level", level.Debug), - log.WithCaller("caller", 2, false), + log.WithSource(3), ) logger.Err(ctx, "same error message") logger.InfoKVs(ctx, "same info message", "api-version", 0.1) _, _ = logger.Write([]byte("same write message")) // Output: - // msg="same error message" level=error caller=logger_example_caller_test.go:14 - // msg="same info message" api-version=0.1 level=info caller=logger_example_caller_test.go:15 - // msg="same write message" level=info caller=logger_example_caller_test.go:16 + // msg="same error message" level=error source=logger_example_caller_test.go:14 + // msg="same info message" api-version=0.1 level=info source=logger_example_caller_test.go:15 + // msg="same write message" level=info source=logger_example_caller_test.go:16 } diff --git a/middleware.go b/middleware.go index 7aad519..8464b1d 100644 --- a/middleware.go +++ b/middleware.go @@ -86,6 +86,7 @@ func WithContextValue(keys ...fmt.Stringer) Middleware { } // WithCaller adds called file. +// Deprecated: use WithSource. func WithCaller(key string, depth int, full bool) Middleware { const offset = 2 diff --git a/source.go b/source.go new file mode 100644 index 0000000..f3fff1d --- /dev/null +++ b/source.go @@ -0,0 +1,45 @@ +package log + +import ( + "context" + "fmt" + "path/filepath" + "runtime" + + "gitoa.ru/go-4devs/log/entry" + "gitoa.ru/go-4devs/log/field" +) + +func WithSource(depth int) Middleware { + const offset = 3 + + return func(ctx context.Context, data *entry.Entry, handler Logger) (int, error) { + pc, file, line, has := runtime.Caller(depth + offset) + if !has { + return handler(ctx, data.AddAny(KeyLevel, field.NilValue())) + } + + fnc := runtime.FuncForPC(pc) + + return handler(ctx, data.AddAny(KeySource, Source{ + Func: filepath.Base(fnc.Name()), + File: filepath.Base(file), + Line: line, + })) + } +} + +// Source describes the location of a line of source code. +type Source struct { + Func string `json:"func"` + File string `json:"file"` + Line int `json:"line"` +} + +func (l Source) MarshalText() ([]byte, error) { + return []byte(fmt.Sprintf("%s:%d", l.File, l.Line)), nil +} + +func (l Source) MarshalJSON() ([]byte, error) { + return fmt.Appendf([]byte{}, `{"file":"%s","line":%d,"func":"%s"}`, l.File, l.Line, l.Func), nil +} diff --git a/source_example_test.go b/source_example_test.go new file mode 100644 index 0000000..82093e7 --- /dev/null +++ b/source_example_test.go @@ -0,0 +1,25 @@ +package log_test + +import ( + "context" + + "gitoa.ru/go-4devs/log" +) + +func ExampleWithSource() { + ctx := context.Background() + logger := log.New(log.WithStdout()).With(log.WithSource(1)) + + logger.Debug(ctx, "debug message") + // Output: + // msg="debug message" source=source_example_test.go:13 +} + +func ExampleWithSource_json() { + ctx := context.Background() + logger := log.New(log.WithStdout(), log.WithJSONFormat()).With(log.WithSource(1)) + + logger.Debug(ctx, "debug message") + // Output: + // {"msg":"debug message","source":{"file":"source_example_test.go","line":22,"func":"log_test.ExampleWithSource_json"}} +} diff --git a/writter.go b/writter.go index 68f83bd..c24ae0d 100644 --- a/writter.go +++ b/writter.go @@ -62,7 +62,7 @@ type option struct { func New(opts ...func(*option)) Logger { log := option{ format: formatText(), - out: os.Stderr, + out: os.Stdout, } for _, opt := range opts {