6 Commits

Author SHA1 Message Date
859a8d88f7 Merge pull request 'update ling and go version' (#17) from format into master
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #17
2024-04-04 12:19:45 +03:00
4baf4b36e7 set golang version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-04-04 12:17:02 +03:00
andrey
2fd0c1f9ec update ling and go version
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2024-04-04 12:12:09 +03:00
c7090b5067 Merge pull request 'use dependency format log' (#16) from format into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #16
2024-04-04 12:08:06 +03:00
andrey
16d3e04fd9 use dependency format log 2024-04-04 12:04:45 +03:00
57a908f894 add bracket format (#15)
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
Reviewed-on: #15
Co-authored-by: andrey <andrey@4devs.io>
Co-committed-by: andrey <andrey@4devs.io>
2024-01-03 21:35:21 +03:00
15 changed files with 143 additions and 95 deletions

View File

@@ -5,7 +5,7 @@ name: logger
steps:
- name: test
image: golang:1.21.5
image: golang:1.22.2
volumes:
- name: deps
path: /go/src/mod
@@ -13,85 +13,10 @@ steps:
- go test
- name: golangci-lint
image: golangci/golangci-lint:v1.55
image: golangci/golangci-lint:v1.57
commands:
- golangci-lint run
volumes:
- name: deps
temp: {}
---
kind: pipeline
type: docker
name: otel
steps:
- name: test
image: golang:1.21.5
volumes:
- name: deps
path: /go/src/mod
commands:
- cd handler/otel
- go test
- name: golangci-lint
image: golangci/golangci-lint:v1.55
commands:
- cd handler/otel
- golangci-lint run
volumes:
- name: deps
temp: {}
---
kind: pipeline
type: docker
name: logrus
steps:
- name: test
image: golang:1.21.5
volumes:
- name: deps
path: /go/src/mod
commands:
- cd handler/logrus
- go test
- name: golangci-lint
image: golangci/golangci-lint:v1.55
commands:
- cd handler/logrus
- golangci-lint run
volumes:
- name: deps
temp: {}
---
kind: pipeline
type: docker
name: zap
steps:
- name: test
image: golang:1.21.5
volumes:
- name: deps
path: /go/src/mod
commands:
- cd handler/zap
- go test
- name: golangci-lint
image: golangci/golangci-lint:v1.55
commands:
- cd handler/zap
- golangci-lint run
volumes:
- name: deps
temp: {}

View File

@@ -73,3 +73,4 @@ issues:
- path: example/*
linters:
- gomnd
- lll

View File

@@ -166,7 +166,9 @@ func BenchmarkDisabledAccumulatedContext(b *testing.B) {
b.Run("4devs/log.Context", func(b *testing.B) {
b.ResetTimer()
logger := NewLogger().With(log.GoVersion("goversion"))
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.InfoKV(ctx, getMessage(0), fakeFields()...)

View File

@@ -2,6 +2,7 @@ package main
import (
"context"
"time"
"gitoa.ru/go-4devs/log"
"gitoa.ru/go-4devs/log/field"
@@ -16,9 +17,13 @@ func main() {
log.Err(ctx, "error message", 42)
service(ctx, log.Log())
logger := log.New(log.WithJSONFormat()).With(log.WithSource(10, log.TrimPath))
logger := log.New(log.WithJSONFormat()).With(log.WithSource(10, log.TrimPath), log.WithTime(log.KeyTime, time.RFC3339))
logger.AlertKV(ctx, "alert message new logger", field.String("string", "value"))
service(ctx, logger)
strLogger := log.New(log.WithFormat(log.FormatWithBracket(field.NewEncoderText()))).With(log.WithSource(10, log.TrimPath), log.WithTime(log.KeyTime, time.RFC3339))
strLogger.AlertKV(ctx, "alert message new txt logger", field.String("string", "value"))
service(ctx, strLogger)
}
func service(ctx context.Context, logger log.Logger) {

View File

@@ -174,6 +174,7 @@ func needsQuoting(in string) bool {
if char != '\\' && (char == ' ' || char == '=' || !safeSet[char]) {
return true
}
i++
continue

View File

@@ -501,3 +501,14 @@ type Field struct {
func (f Field) String() string {
return fmt.Sprintf("%s=%+v", f.Key, f.Value)
}
// String implent stringer.
func (f Field) IsKey(keys ...string) bool {
for _, key := range keys {
if key == f.Key {
return true
}
}
return false
}

View File

@@ -3,6 +3,7 @@ package log
import (
"context"
"io"
"time"
"gitoa.ru/go-4devs/log/field"
"gitoa.ru/go-4devs/log/level"
@@ -10,7 +11,7 @@ import (
//nolint:gochecknoglobals,gomnd
var global = With(New(),
WithSource(2, TrimPath),
WithTime(KeyTime, time.RFC3339),
WithLevel(KeyLevel, level.Debug),
WithExit(level.Alert),
WithPanic(level.Emergency),

View File

@@ -11,11 +11,13 @@ import (
)
// Standard create new standart logrus handler.
// Deprecated: delete after 0.7.0
func Standard() log.Logger {
return New(logrus.StandardLogger())
}
// New create new logrus handler.
// Deprecated: delete after 0.7.0
func New(log *logrus.Logger) log.Logger {
return func(ctx context.Context, data *entry.Entry) (int, error) {
lrgFields := make(logrus.Fields, data.Fields().Len())

View File

@@ -7,6 +7,7 @@ import (
"gitoa.ru/go-4devs/log/entry"
)
// Deprecated: delete after 0.7.0
func New() log.Logger {
return func(ctx context.Context, e *entry.Entry) (int, error) {
addEvent(ctx, e)

View File

@@ -7,6 +7,7 @@ import (
"gitoa.ru/go-4devs/log/entry"
)
// Deprecated: delete after 0.7.0
func Middleware() log.Middleware {
return func(ctx context.Context, e *entry.Entry, handler log.Logger) (int, error) {
addEvent(ctx, e)

View File

@@ -10,14 +10,17 @@ import (
"go.uber.org/zap"
)
// Deprecated: delete after 0.7.0
func Nop() log.Logger {
return New(zap.NewNop())
}
// Deprecated: delete after 0.7.0
func Example(options ...zap.Option) log.Logger {
return New(zap.NewExample(options...))
}
// Deprecated: delete after 0.7.0
func Production(options ...zap.Option) log.Logger {
z, err := zap.NewProduction(options...)
if err != nil {
@@ -27,6 +30,7 @@ func Production(options ...zap.Option) log.Logger {
return New(z)
}
// Deprecated: delete after 0.7.0
func Development(options ...zap.Option) log.Logger {
z, err := zap.NewDevelopment(options...)
if err != nil {

View File

@@ -213,8 +213,8 @@ func ExampleNew_jsonFormat() {
logger.Err(ctx, "same error message")
logger.WarnKVs(ctx, "same warn message", "obj", Obj{Name: "obj name"})
// Output:
// {"msg":"same error message","level":"error","go-version":"go1.21.5"}
// {"msg":"same warn message","obj":{"Name":"obj name","IsEnable":false},"level":"warning","go-version":"go1.21.5"}
// {"msg":"same error message","level":"error","go-version":"go1.22.2"}
// {"msg":"same warn message","obj":{"Name":"obj name","IsEnable":false},"level":"warning","go-version":"go1.22.2"}
}
func ExampleNew_textEncoding() {
@@ -227,8 +227,8 @@ func ExampleNew_textEncoding() {
logger.InfoKVs(ctx, "same info message", "api-version", 0.1, "obj", Obj{Name: "text value", IsEnable: true})
// Output:
// msg="same error message" level=error go-version=go1.21.5
// msg="same info message" api-version=0.1 obj={Name:text value IsEnable:true} level=info go-version=go1.21.5
// msg="same error message" level=error go-version=go1.22.2
// msg="same info message" api-version=0.1 obj={Name:text value IsEnable:true} level=info go-version=go1.22.2
}
type ctxKey string
@@ -252,7 +252,7 @@ func ExampleWith() {
log.GoVersion("go"),
)
logger.Info(vctx, "same message")
// Output: msg="same message" level=info requestID=6a5fa048-7181-11ea-bc55-0242ac130003 api=0.1.0 go=go1.21.5
// Output: msg="same message" level=info requestID=6a5fa048-7181-11ea-bc55-0242ac130003 api=0.1.0 go=go1.22.2
}
func ExampleLogger_Print() {
@@ -263,7 +263,7 @@ func ExampleLogger_Print() {
log.GoVersion("go"),
)
logger.Print("same message")
// Output: msg="same message" level=info client=http api=0.1.0 go=go1.21.5
// Output: msg="same message" level=info client=http api=0.1.0 go=go1.22.2
}
func ExamplePrint() {

View File

@@ -38,6 +38,7 @@ func With(logger Logger, mw ...Middleware) Logger {
if curI == lastI {
return logger(currentCtx, currentEntry)
}
curI++
n, err := mw[curI](currentCtx, currentEntry, chainHandler)
curI--

37
writer_example_test.go Normal file
View File

@@ -0,0 +1,37 @@
package log_test
import (
"context"
"math"
"path/filepath"
"time"
"gitoa.ru/go-4devs/log"
"gitoa.ru/go-4devs/log/entry"
"gitoa.ru/go-4devs/log/field"
"gitoa.ru/go-4devs/log/level"
)
func exampleWithTime(key, format string) log.Middleware {
return func(ctx context.Context, e *entry.Entry, handler log.Logger) (int, error) {
return handler(ctx, e.Add(field.FormatTime(key, format, time.Unix(math.MaxInt32, 0).In(time.UTC))))
}
}
func ExampleFormatWithBracket() {
ctx := context.Background()
logger := log.New(log.WithFormat(log.FormatWithBracket(field.NewEncoderText())), log.WithStdout()).With(
log.WithSource(10, filepath.Base),
// log.WithTime(log.KeyTime, time.RFC3339),
exampleWithTime(log.KeyTime, time.RFC3339),
log.WithLevel(log.KeyLevel, level.Info),
)
logger.InfoKV(ctx, "imfo message", field.Int64("num", 42))
serviceLogger := logger.With(log.WithName("service_name"))
serviceLogger.Err(ctx, "error message")
// Output:
// 2038-01-19T03:14:07Z [info] writer_example_test.go:30 "imfo message" num=42
// 2038-01-19T03:14:07Z [error][service_name] writer_example_test.go:33 "error message"
}

View File

@@ -43,15 +43,18 @@ func WithStdout() func(*option) {
// WithStringFormat sets format as simple string.
func WithStringFormat() func(*option) {
return func(o *option) {
o.format = formatText()
}
return WithFormat(FormatString(field.NewEncoderText()))
}
// WithJSONFormat sets json output format.
func WithJSONFormat() func(*option) {
return WithFormat(FormatJSON(field.NewEncoderJSON()))
}
// WithFormat sets custom output format.
func WithFormat(format func(io.Writer, *entry.Entry) (int, error)) func(*option) {
return func(o *option) {
o.format = formatJSON()
o.format = format
}
}
@@ -63,7 +66,7 @@ type option struct {
// New creates standart logger.
func New(opts ...func(*option)) Logger {
log := option{
format: formatText(),
format: FormatString(field.NewEncoderText()),
out: os.Stderr,
}
@@ -76,9 +79,64 @@ func New(opts ...func(*option)) Logger {
}
}
func formatText() func(io.Writer, *entry.Entry) (int, error) {
enc := field.NewEncoderText()
type Encoder interface {
AppendValue(dst []byte, val field.Value) []byte
AppendField(dst []byte, val field.Field) []byte
}
func FormatWithBracket(enc Encoder) func(io.Writer, *entry.Entry) (int, error) {
appendValue := func(buf *buffer.Buffer, data field.Fields, key, prefix, suffix string) *buffer.Buffer {
data.Fields(
func(f field.Field) bool {
if f.IsKey(key) {
_, _ = buf.WriteString(prefix)
*buf = enc.AppendValue(*buf, f.Value)
_, _ = buf.WriteString(suffix)
return false
}
return true
})
return buf
}
return func(w io.Writer, data *entry.Entry) (int, error) {
buf := buffer.New()
defer func() {
buf.Free()
}()
fields := data.Fields()
buf = appendValue(buf, fields, KeyTime, "", " ")
_, _ = buf.WriteString("[")
*buf = enc.AppendValue(*buf, field.StringValue(data.Level().String()))
_, _ = buf.WriteString("]")
buf = appendValue(buf, fields, KeyName, "[", "]")
buf = appendValue(buf, fields, KeySource, " ", " ")
*buf = enc.AppendValue(*buf, field.StringValue(data.Message()))
fields.Fields(func(f field.Field) bool {
if !f.IsKey(KeyTime, KeySource, KeyName, KeyLevel) {
*buf = enc.AppendField(*buf, f)
}
return true
})
_, _ = buf.WriteString("\n")
n, err := w.Write(*buf)
if err != nil {
return 0, fmt.Errorf("format text:%w", err)
}
return n, nil
}
}
func FormatString(enc Encoder) func(io.Writer, *entry.Entry) (int, error) {
return func(w io.Writer, entry *entry.Entry) (int, error) {
buf := buffer.New()
defer func() {
@@ -102,9 +160,7 @@ func formatText() func(io.Writer, *entry.Entry) (int, error) {
}
}
func formatJSON() func(w io.Writer, entry *entry.Entry) (int, error) {
enc := field.NewEncoderJSON()
func FormatJSON(enc Encoder) func(w io.Writer, entry *entry.Entry) (int, error) {
return func(w io.Writer, entry *entry.Entry) (int, error) {
buf := buffer.New()
defer func() {