Merge pull request 'log' (#20) from log into master
All checks were successful
Go Action / goaction (push) Successful in 31s

Reviewed-on: #20
This commit was merged in pull request #20.
This commit is contained in:
2026-03-02 19:31:00 +03:00
21 changed files with 256 additions and 125 deletions

View File

@@ -17,7 +17,7 @@ jobs:
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v8 # Use the golangci-lint action
with:
version: v2.7.2 # Specify the linter version
version: v2.10.1 # Specify the linter version
# Optional: additional arguments
args: --verbose

View File

@@ -4,6 +4,7 @@ linters:
disable:
- wsl
- noinlineerr
- revive
settings:
depguard:
rules:
@@ -21,20 +22,11 @@ linters:
- "*.UnmarshalText"
- "*.UnmarshalJSON"
- "*.UnmarshalBinary"
dupl:
threshold: 100
exhaustive:
default-signifies-exhaustive: true
funlen:
lines: 100
statements: 50
goconst:
min-len: 2
min-occurrences: 2
gocyclo:
min-complexity: 15
lll:
line-length: 140
misspell:
locale: US
tagliatelle:

View File

@@ -163,18 +163,7 @@ func (e *Entry) AddString(key, value string) *Entry {
}
func (e *Entry) Replace(key string, value field.Value) *Entry {
has := false
e.fields.Fields(func(f field.Field) bool {
if f.Key == key {
f.Value = value
has = true
return false
}
return true
})
_, has := e.fields.Replace(field.Any(key, value))
if !has {
e.AddAny(key, value)

42
entry/entry_test.go Normal file
View File

@@ -0,0 +1,42 @@
package entry_test
import (
"testing"
"time"
"gitoa.ru/go-4devs/log/entry"
"gitoa.ru/go-4devs/log/field"
)
func TestEntry_Replace(t *testing.T) {
t.Parallel()
ent := entry.New(entry.WithFields(
field.Any("inti", "init date"),
))
ent = ent.Replace("date", field.StringValue("some date"))
ent = ent.Replace("date", field.TimeValue(time.Time{}))
fields := ent.Fields()
if len(fields) != 2 {
t.Fatalf("count must be 2 got %v", len(fields))
}
var has bool
fields.Fields(func(f field.Field) bool {
if f.Key == "date" && !f.Value.AsTime().IsZero() {
has = true
return false
}
return true
})
if !has {
t.Fatal("failed reace value")
}
}

View File

@@ -31,7 +31,14 @@ func WithDelimeter(in byte) func(*BaseEncoder) {
}
}
// WithGropuConfig set group config.
//
// Deprecated: use WithGroupConfig.
func WithGropuConfig(start, end, deli byte) func(*BaseEncoder) {
return WithGroupConfig(start, end, deli)
}
func WithGroupConfig(start, end, deli byte) func(*BaseEncoder) {
return func(be *BaseEncoder) {
be.group = groupConfig{
start: start,
@@ -243,7 +250,7 @@ func (b BaseEncoder) appendField(dst []byte, field Field, prefix string, deli by
return b.appendValue(dst, field.Value, field.Key+".", deli)
}
//nolint:mnd,gocyclo,cyclop
//nolint:mnd,cyclop
func (b BaseEncoder) appendValue(dst []byte, val Value, prefix string, deli byte) []byte {
switch val.Kind {
case KindGroup:
@@ -269,7 +276,12 @@ func (b BaseEncoder) appendValue(dst []byte, val Value, prefix string, deli byte
case KindUint64:
return b.AppendUint(b.AppendDelimiter(dst, deli), val.AsUint64())
case KindError:
return b.AppendString(b.AppendDelimiter(dst, deli), val.AsError().Error())
var errData string
if err := val.AsError(); err != nil {
errData = err.Error()
}
return b.AppendString(b.AppendDelimiter(dst, deli), errData)
case KindString:
return b.AppendString(b.AppendDelimiter(dst, deli), val.AsString())
case KindDuration:

View File

@@ -7,7 +7,7 @@ import (
func NewEncoderText(opts ...func(*BaseEncoder)) BaseEncoder {
opts = append([]func(*BaseEncoder){
WithGropuConfig(0, 0, ' '),
WithGroupConfig(0, 0, ' '),
WithNullValue("<nil>"),
WithDefaultValue(func(dst []byte, enc Encoder, val Value) []byte {
switch value := val.Any().(type) {

View File

@@ -2,4 +2,4 @@ package field
import "errors"
var ErrUndefined = errors.New("indefined")
var ErrUndefined = errors.New("undefined")

View File

@@ -6,6 +6,13 @@ import (
"time"
)
//nolint:gochecknoglobals
var empty Field
func Empty() Field {
return empty
}
func Any(key string, value any) Field {
return Field{
Key: key,
@@ -498,7 +505,7 @@ type Field struct {
Value Value
}
// String implent stringer.
// String implement stringer.
func (f Field) String() string {
return fmt.Sprintf("%s=%+v", f.Key, f.Value)
}

View File

@@ -32,3 +32,16 @@ func (f Fields) Set(idx int, field Field) {
func (f Fields) Len() int {
return len(f)
}
func (f Fields) Replace(field Field) (Field, bool) {
for idx := range f {
if f[idx].Key == field.Key {
old := f[idx]
f[idx] = field
return old, true
}
}
return Empty(), false
}

View File

@@ -16,3 +16,22 @@ func TestFields_Append(t *testing.T) {
t.Fatalf("require 2 field got %v", len(fields))
}
}
func TestFields_Replace(t *testing.T) {
t.Parallel()
fields := field.Fields{
field.Any("any", "any init"),
field.Any("replace", "replace init"),
}
old, ok := fields.Replace(field.Int64("replace", 42))
if !ok || old.Key != "replace" || old.Value != field.StringValue("replace init") {
t.Fatalf("failed replace value:%v", old)
}
o2, ok2 := fields.Replace(field.Any("new", "new data"))
if ok2 || o2.Key != "" {
t.Fatalf("failed set new data:%v", o2)
}
}

View File

@@ -37,44 +37,76 @@ func (l Kind) MarshalText() ([]byte, error) {
return []byte(l.String()), nil
}
//nolint:gocyclo,cyclop
//nolint:cyclop,funlen
func (l *Kind) UnmarshalText(in []byte) error {
switch string(in) {
case KindAny.String():
*l = KindAny
return nil
case KindArray.String():
*l = KindArray
return nil
case KindNil.String():
*l = KindNil
return nil
case KindString.String():
*l = KindString
return nil
case KindBool.String():
*l = KindBool
return nil
case KindInt64.String():
*l = KindInt64
return nil
case KindUint64.String():
*l = KindUint64
return nil
case KindFloat32.String():
*l = KindFloat32
return nil
case KindFloat64.String():
*l = KindFloat64
return nil
case KindComplex128.String():
*l = KindComplex128
return nil
case KindBinary.String():
*l = KindBinary
return nil
case KindDuration.String():
*l = KindDuration
return nil
case KindTime.String():
*l = KindTime
return nil
case KindError.String():
*l = KindError
return nil
case KindGroup.String():
*l = KindGroup
return nil
case KindClosure.String():
*l = KindClosure
}
return fmt.Errorf("%w:filed(%v)", ErrUndefined, string(in))
return nil
default:
return fmt.Errorf("%w:filed(%v)", ErrUndefined, string(in))
}
}
func (l Kind) MarshalBinary() ([]byte, error) {

View File

@@ -469,7 +469,7 @@ func (v Value) String() string {
return string(v.append(buf))
}
//nolint:gocyclo,cyclop
//nolint:cyclop
func (v Value) Any() any {
switch v.Kind {
case KindAny, KindBinary:

View File

@@ -29,209 +29,209 @@ func Log() Logger {
// Emerg log by emergency level.
func Emerg(ctx context.Context, args ...any) {
global.Emerg(ctx, args...)
Log().Emerg(ctx, args...)
}
// Alert log by alert level.
func Alert(ctx context.Context, args ...any) {
global.Alert(ctx, args...)
Log().Alert(ctx, args...)
}
// Crit log by critical level.
func Crit(ctx context.Context, args ...any) {
global.Crit(ctx, args...)
Log().Crit(ctx, args...)
}
// Err log by error level.
func Err(ctx context.Context, args ...any) {
global.Err(ctx, args...)
Log().Err(ctx, args...)
}
// Warn logs by warning level.
func Warn(ctx context.Context, args ...any) {
global.Warn(ctx, args...)
Log().Warn(ctx, args...)
}
// Notice log by notice level.
func Notice(ctx context.Context, args ...any) {
global.Notice(ctx, args...)
Log().Notice(ctx, args...)
}
// Info log by info level.
func Info(ctx context.Context, args ...any) {
global.Info(ctx, args...)
Log().Info(ctx, args...)
}
// Debug log by debug level.
func Debug(ctx context.Context, args ...any) {
global.Debug(ctx, args...)
Log().Debug(ctx, args...)
}
// Print log by info level and arguments.
func Print(args ...any) {
global.Print(args...)
Log().Print(args...)
}
// Fatal log by alert level and arguments.
func Fatal(args ...any) {
global.Fatal(args...)
Log().Fatal(args...)
}
// Panic log by emergency level and arguments.
func Panic(args ...any) {
global.Panic(args...)
Log().Panic(args...)
}
// Println log by info level and arguments.
func Println(args ...any) {
global.Println(args...)
Log().Println(args...)
}
// Fatalln log by alert level and arguments.
func Fatalln(args ...any) {
global.Fatalln(args...)
Log().Fatalln(args...)
}
// Panicln log by emergency level and arguments.
func Panicln(args ...any) {
global.Panicln(args...)
Log().Panicln(args...)
}
// EmergKVs sugared log by emergency level and key-values.
func EmergKVs(ctx context.Context, msg string, args ...any) {
global.EmergKVs(ctx, msg, args...)
Log().EmergKVs(ctx, msg, args...)
}
// AlertKVs sugared log by alert level and key-values.
func AlertKVs(ctx context.Context, msg string, args ...any) {
global.AlertKVs(ctx, msg, args...)
Log().AlertKVs(ctx, msg, args...)
}
// CritKVs sugared log by critcal level and key-values.
// CritKVs sugared log by critical level and key-values.
func CritKVs(ctx context.Context, msg string, args ...any) {
global.CritKVs(ctx, msg, args...)
Log().CritKVs(ctx, msg, args...)
}
// ErrKVs sugared log by error level and key-values.
func ErrKVs(ctx context.Context, msg string, args ...any) {
global.ErrKVs(ctx, msg, args...)
Log().ErrKVs(ctx, msg, args...)
}
// WarnKVs sugared log by warning level and key-values.
func WarnKVs(ctx context.Context, msg string, args ...any) {
global.WarnKVs(ctx, msg, args...)
Log().WarnKVs(ctx, msg, args...)
}
// NoticeKVs sugared log by notice level and key-values.
func NoticeKVs(ctx context.Context, msg string, args ...any) {
global.NoticeKVs(ctx, msg, args...)
Log().NoticeKVs(ctx, msg, args...)
}
// InfoKVs sugared log by info level and key-values.
func InfoKVs(ctx context.Context, msg string, args ...any) {
global.InfoKVs(ctx, msg, args...)
Log().InfoKVs(ctx, msg, args...)
}
// DebugKVs sugared log by debug level and key-values.
func DebugKVs(ctx context.Context, msg string, args ...any) {
global.DebugKVs(ctx, msg, args...)
Log().DebugKVs(ctx, msg, args...)
}
// EmergKV log by emergency level and key-values.
func EmergKV(ctx context.Context, msg string, args ...field.Field) {
global.EmergKV(ctx, msg, args...)
Log().EmergKV(ctx, msg, args...)
}
// AlertKV log by alert level and key-values.
func AlertKV(ctx context.Context, msg string, args ...field.Field) {
global.AlertKV(ctx, msg, args...)
Log().AlertKV(ctx, msg, args...)
}
// CritKV log by critcal level and key-values.
// CritKV log by critical level and key-values.
func CritKV(ctx context.Context, msg string, args ...field.Field) {
global.CritKV(ctx, msg, args...)
Log().CritKV(ctx, msg, args...)
}
// ErrKV log by error level and key-values.
func ErrKV(ctx context.Context, msg string, args ...field.Field) {
global.ErrKV(ctx, msg, args...)
Log().ErrKV(ctx, msg, args...)
}
// WarnKV log by warning level and key-values.
func WarnKV(ctx context.Context, msg string, args ...field.Field) {
global.WarnKV(ctx, msg, args...)
Log().WarnKV(ctx, msg, args...)
}
// NoticeKV log by notice level and key-values.
func NoticeKV(ctx context.Context, msg string, args ...field.Field) {
global.NoticeKV(ctx, msg, args...)
Log().NoticeKV(ctx, msg, args...)
}
// InfoKV log by info level and key-values.
func InfoKV(ctx context.Context, msg string, args ...field.Field) {
global.InfoKV(ctx, msg, args...)
Log().InfoKV(ctx, msg, args...)
}
// DebugKV log by debug level and key-values.
func DebugKV(ctx context.Context, msg string, args ...field.Field) {
global.DebugKV(ctx, msg, args...)
Log().DebugKV(ctx, msg, args...)
}
// Emergf log by emergency level by format and arguments.
func Emergf(ctx context.Context, format string, args ...any) {
global.Emergf(ctx, format, args...)
Log().Emergf(ctx, format, args...)
}
// Alertf log by alert level by format and arguments.
func Alertf(ctx context.Context, format string, args ...any) {
global.Alertf(ctx, format, args...)
Log().Alertf(ctx, format, args...)
}
// Critf log by critical level by format and arguments.
func Critf(ctx context.Context, format string, args ...any) {
global.Critf(ctx, format, args...)
Log().Critf(ctx, format, args...)
}
// Errf log by error level by format and arguments.
func Errf(ctx context.Context, format string, args ...any) {
global.Errf(ctx, format, args...)
Log().Errf(ctx, format, args...)
}
// Warnf log by warning level by format and arguments.
func Warnf(ctx context.Context, format string, args ...any) {
global.Warnf(ctx, format, args...)
Log().Warnf(ctx, format, args...)
}
// Noticef log by notice level by format and arguments.
func Noticef(ctx context.Context, format string, args ...any) {
global.Noticef(ctx, format, args...)
Log().Noticef(ctx, format, args...)
}
// Infof log by info level by format and arguments.
func Infof(ctx context.Context, format string, args ...any) {
global.Noticef(ctx, format, args...)
Log().Infof(ctx, format, args...)
}
// Debugf log by debug level by format and arguments.
func Debugf(ctx context.Context, format string, args ...any) {
global.Debugf(ctx, format, args...)
Log().Debugf(ctx, format, args...)
}
// Printf log by info level by format and arguments without context.
func Printf(format string, args ...any) {
global.Printf(format, args...)
Log().Printf(format, args...)
}
// Fatalf log by alert level by format and arguments without context.
func Fatalf(format string, args ...any) {
global.Fatalf(format, args...)
Log().Fatalf(format, args...)
}
// Panicf log by emergency level and arguments without context.
func Panicf(format string, args ...any) {
global.Panicf(format, args...)
Log().Panicf(format, args...)
}
func Writer(ctx context.Context, level level.Level) io.Writer {
return global.Writer(ctx, level)
return Log().Writer(ctx, level)
}

View File

@@ -10,7 +10,7 @@ import (
"gitoa.ru/go-4devs/log/level"
)
// Standard create new standart logrus handler.
// Standard create new standard logrus handler.
// Deprecated: delete after 0.7.0
func Standard() log.Logger {
return New(logrus.StandardLogger())

View File

@@ -75,19 +75,19 @@ func (l *Level) UnmarshalBinary(in []byte) error {
func Parse(lvl string) Level {
switch strings.ToLower(lvl) {
case "debug", "Debug", "DEBUG":
case "debug":
return Debug
case "info", "Info", "INFO":
case "info":
return Info
case "notice", "Notice", "NOTICE":
case "notice":
return Notice
case "warning", "Warning", "WARNING", "warm", "Warm", "WARN":
case "warning", "warn":
return Warning
case "error", "Error", "ERROR", "err", "Err", "ERR":
case "error", "err":
return Error
case "critical", "Critical", "CRITICAL", "crit", "Crit", "CRIT":
case "critical", "crit":
return Critical
case "alert", "Alert", "ALERT":
case "alert":
return Alert
default:
return Emergency

View File

@@ -105,42 +105,42 @@ func (l Logger) Panicln(args ...any) {
// EmergKVs sugared log by emergency level and key-values.
func (l Logger) EmergKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Emergency, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Emergency, msg, args))
}
// AlertKVs sugared log by alert level and key-values.
func (l Logger) AlertKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Alert, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Alert, msg, args))
}
// CritKVs sugared log by critcal level and key-values.
// CritKVs sugared log by critical level and key-values.
func (l Logger) CritKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Critical, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Critical, msg, args))
}
// ErrKVs sugared log by error level and key-values.
func (l Logger) ErrKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Error, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Error, msg, args))
}
// WarnKVs sugared log by warning level and key-values.
func (l Logger) WarnKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Warning, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Warning, msg, args))
}
// NoticeKVs sugared log by notice level and key-values.
func (l Logger) NoticeKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Notice, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Notice, msg, args))
}
// InfoKVs sugared log by info level and key-values.
func (l Logger) InfoKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Info, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Info, msg, args))
}
// DebugKVs sugared log by debug level and key-values.
func (l Logger) DebugKVs(ctx context.Context, msg string, args ...any) {
writeOutput(l.write(ctx, level.Debug, msg, l.kv(ctx, args...)...))
writeOutput(l.writekvs(ctx, level.Debug, msg, args))
}
// EmergKV log by emergency level and key-values.
@@ -153,7 +153,7 @@ func (l Logger) AlertKV(ctx context.Context, msg string, args ...field.Field) {
writeOutput(l.write(ctx, level.Alert, msg, args...))
}
// CritKV log by critcal level and key-values.
// CritKV log by critical level and key-values.
func (l Logger) CritKV(ctx context.Context, msg string, args ...field.Field) {
writeOutput(l.write(ctx, level.Critical, msg, args...))
}
@@ -247,38 +247,39 @@ func (l Logger) Writer(ctx context.Context, level level.Level, fields ...field.F
}
}
func (l Logger) kv(_ context.Context, args ...any) field.Fields {
kvEntry := entry.Get()
func (l Logger) writekvs(ctx context.Context, lvl level.Level, mst string, args []any) (int, error) {
data := entry.Get()
data = data.SetMessage(mst).SetLevel(lvl)
defer func() {
entry.Put(kvEntry)
entry.Put(data)
}()
for i := 0; i < len(args); i++ {
if f, ok := args[i].(field.Field); ok {
kvEntry = kvEntry.Add(f)
data = data.Add(f)
continue
}
if i == len(args)-1 {
kvEntry = kvEntry.AddAny(badKey, args[i])
data = data.AddAny(badKey, args[i])
break
}
key, val := args[i], args[i+1]
if keyStr, ok := key.(string); ok {
kvEntry = kvEntry.AddAny(keyStr, val)
data = data.AddAny(keyStr, val)
i++
continue
}
kvEntry = kvEntry.AddAny(badKey, args[i])
data = data.AddAny(badKey, args[i])
}
return kvEntry.Fields()
return l(ctx, data)
}
func (l Logger) write(ctx context.Context, level level.Level, msg string, fields ...field.Field) (int, error) {

View File

@@ -28,7 +28,8 @@ func TestFields(t *testing.T) {
buf := &bytes.Buffer{}
log := log.New(log.WithWriter(buf)).
With(log.WithLevel(log.KeyLevel, level.Info))
success := "msg=message err=\"file already exists\" version=0.1.0 obj={id:uid} closure=\"some closure data\" level=info\n"
success := "msg=message err=\"file already exists\"" +
" version=0.1.0 obj={id:uid} closure=\"some closure data\" level=info\n"
log.InfoKVs(ctx, "message",
"err", os.ErrExist,
@@ -63,7 +64,8 @@ func TestWriter(t *testing.T) {
ctx := context.Background()
success := "msg=\"info message\" err=\"file already exists\" requestID=6a5fa048-7181-11ea-bc55-0242ac1311113 level=info\n"
success := "msg=\"info message\" err=\"file already exists\"" +
" requestID=6a5fa048-7181-11ea-bc55-0242ac1311113 level=info\n"
buf := &bytes.Buffer{}
logger := log.New(log.WithWriter(buf)).With(log.WithContextValue(requestID), log.WithLevel(log.KeyLevel, level.Info))

View File

@@ -17,7 +17,9 @@ type Middleware func(ctx context.Context, e *entry.Entry, handler Logger) (int,
// With add middleware to logger.
func With(logger Logger, mw ...Middleware) Logger {
switch len(mw) {
num := len(mw)
switch num {
case 0:
return logger
case 1:
@@ -26,27 +28,17 @@ func With(logger Logger, mw ...Middleware) Logger {
}
}
lastI := len(mw) - 1
return func(ctx context.Context, data *entry.Entry) (int, error) {
var (
chainHandler func(context.Context, *entry.Entry) (int, error)
curI int
)
currHandler := logger
chainHandler = func(currentCtx context.Context, currentEntry *entry.Entry) (int, error) {
if curI == lastI {
return logger(currentCtx, currentEntry)
for i := num - 1; i > 0; i-- {
innerHandler := currHandler
currHandler = func(currentCtx context.Context, currentEntry *entry.Entry) (int, error) {
return mw[i](currentCtx, currentEntry, innerHandler)
}
curI++
n, err := mw[curI](currentCtx, currentEntry, chainHandler)
curI--
return n, err
}
return mw[0](ctx, data, chainHandler)
return mw[0](ctx, data, currHandler)
}
}

View File

@@ -11,14 +11,21 @@ import (
"gitoa.ru/go-4devs/log/field"
)
const funcName = "Logger"
func WithSource(items int, trimPath func(string) string) Middleware {
const (
skip = 4
funcPrefix = "gitoa.ru/go-4devs/log.Logger"
skipHelper = "gitoa.ru/go-4devs/log."
skip = 4
pkgName = "gitoa.ru/go-4devs/log"
)
return WithCallers(items, skip, pkgName, trimPath)
}
func WithCallers(items, skip int, logPkg string, trimPath func(string) string) Middleware {
items += skip
skipHelper := logPkg + "."
funcPrefix := skipHelper + funcName
return func(ctx context.Context, data *entry.Entry, handler Logger) (int, error) {
pc := make([]uintptr, items)
@@ -86,7 +93,7 @@ func (l Source) MarshalText() ([]byte, error) {
}
func (l Source) MarshalJSON() ([]byte, error) {
return fmt.Appendf([]byte{}, `{"file":"%s","line":%d,"func":"%s"}`, l.File, l.Line, l.Func), nil
return fmt.Appendf([]byte{}, `{"file":%q,"line":%d,"func":"%s"}`, l.File, l.Line, l.Func), nil
}
func errSourceField(skip, mframe int) field.Field {

23
source_test.go Normal file
View File

@@ -0,0 +1,23 @@
package log_test
import (
"encoding/json"
"testing"
"gitoa.ru/go-4devs/log"
)
func TestSource_MarshalJSON(t *testing.T) {
t.Parallel()
src := log.Source{
Func: "fn name",
File: `file " \n name`,
Line: 42,
}
data, err := json.Marshal(src)
if err != nil || len(data) == 0 || string(data) != `{"file":"file \" \\n name","line":42,"func":"fn name"}` {
t.Fatalf("failed marshal: err=%v, data=%v", err, string(data))
}
}

View File

@@ -63,7 +63,7 @@ type option struct {
out io.Writer
}
// New creates standart logger.
// New creates standard logger.
func New(opts ...func(*option)) Logger {
log := option{
format: FormatString(field.NewEncoderText()),