add bracket format #15

Merged
andrey merged 5 commits from bracket into master 11 months ago
  1. 75
      .drone.yml
  2. 1
      .golangci.yml
  3. 7
      example/log.go
  4. 11
      field/field.go
  5. 3
      global.go
  6. 2
      handler/logrus/logger.go
  7. 1
      handler/otel/logger.go
  8. 1
      handler/otel/middleware.go
  9. 4
      handler/zap/logger.go
  10. 37
      writer_example_test.go
  11. 69
      writter.go

75
.drone.yml

@ -20,78 +20,3 @@ steps:
volumes: volumes:
- name: deps - name: deps
temp: {} 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: {}

1
.golangci.yml

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

7
example/log.go

@ -2,6 +2,7 @@ package main
import ( import (
"context" "context"
"time"
"gitoa.ru/go-4devs/log" "gitoa.ru/go-4devs/log"
"gitoa.ru/go-4devs/log/field" "gitoa.ru/go-4devs/log/field"
@ -16,9 +17,13 @@ func main() {
log.Err(ctx, "error message", 42) log.Err(ctx, "error message", 42)
service(ctx, log.Log()) 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")) logger.AlertKV(ctx, "alert message new logger", field.String("string", "value"))
service(ctx, logger) service(ctx, logger)
strLogger := log.New(log.WithFormat(log.FormatWithBracket())).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) { func service(ctx context.Context, logger log.Logger) {

11
field/field.go

@ -501,3 +501,14 @@ type Field struct {
func (f Field) String() string { func (f Field) String() string {
return fmt.Sprintf("%s=%+v", f.Key, f.Value) 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
}

3
global.go

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

2
handler/logrus/logger.go

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

1
handler/otel/logger.go

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

1
handler/otel/middleware.go

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

4
handler/zap/logger.go

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

37
writer_example_test.go

@ -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()), 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"
}

69
writter.go

@ -43,15 +43,18 @@ func WithStdout() func(*option) {
// WithStringFormat sets format as simple string. // WithStringFormat sets format as simple string.
func WithStringFormat() func(*option) { func WithStringFormat() func(*option) {
return func(o *option) { return WithFormat(formatString())
o.format = formatText()
}
} }
// WithJSONFormat sets json output format. // WithJSONFormat sets json output format.
func WithJSONFormat() func(*option) { func WithJSONFormat() func(*option) {
return WithFormat(formatJSON())
}
// WithFormat sets custom output format.
func WithFormat(format func(io.Writer, *entry.Entry) (int, error)) func(*option) {
return func(o *option) { return func(o *option) {
o.format = formatJSON() o.format = format
} }
} }
@ -63,7 +66,7 @@ type option struct {
// New creates standart logger. // New creates standart logger.
func New(opts ...func(*option)) Logger { func New(opts ...func(*option)) Logger {
log := option{ log := option{
format: formatText(), format: formatString(),
out: os.Stderr, out: os.Stderr,
} }
@ -76,7 +79,61 @@ func New(opts ...func(*option)) Logger {
} }
} }
func formatText() func(io.Writer, *entry.Entry) (int, error) { func FormatWithBracket() func(io.Writer, *entry.Entry) (int, error) {
enc := field.NewEncoderText()
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() func(io.Writer, *entry.Entry) (int, error) {
enc := field.NewEncoderText() enc := field.NewEncoderText()
return func(w io.Writer, entry *entry.Entry) (int, error) { return func(w io.Writer, entry *entry.Entry) (int, error) {

Loading…
Cancel
Save