You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
4.1 KiB
188 lines
4.1 KiB
package log
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
"gitoa.ru/go-4devs/log/entry"
|
|
"gitoa.ru/go-4devs/log/field"
|
|
"gitoa.ru/go-4devs/log/internal/buffer"
|
|
)
|
|
|
|
// Keys for "built-in" attributes.
|
|
const (
|
|
// TimeKey is the key used by the built-in handlers for the time
|
|
// when the log method is called. The associated Value is a [time.Time].
|
|
KeyTime = "time"
|
|
// LevelKey is the key used by the built-in handlers for the level
|
|
// of the log call. The associated value is a [Level].
|
|
KeyLevel = "level"
|
|
// MessageKey is the key used by the built-in handlers for the
|
|
// message of the log call. The associated value is a string.
|
|
KeyMessage = "msg"
|
|
// SourceKey is the key used by the built-in handlers for the source file
|
|
// and line of the log call. The associated value is a string.
|
|
KeySource = "source"
|
|
// KeyName logger name.
|
|
KeyName = "name"
|
|
)
|
|
|
|
func WithWriter(w io.Writer) func(*option) {
|
|
return func(o *option) {
|
|
o.out = w
|
|
}
|
|
}
|
|
|
|
func WithStdout() func(*option) {
|
|
return func(o *option) {
|
|
o.out = os.Stdout
|
|
}
|
|
}
|
|
|
|
// WithStringFormat sets format as simple string.
|
|
func WithStringFormat() func(*option) {
|
|
return WithFormat(formatString())
|
|
}
|
|
|
|
// WithJSONFormat sets json output format.
|
|
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) {
|
|
o.format = format
|
|
}
|
|
}
|
|
|
|
type option struct {
|
|
format func(io.Writer, *entry.Entry) (int, error)
|
|
out io.Writer
|
|
}
|
|
|
|
// New creates standart logger.
|
|
func New(opts ...func(*option)) Logger {
|
|
log := option{
|
|
format: formatString(),
|
|
out: os.Stderr,
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(&log)
|
|
}
|
|
|
|
return func(_ context.Context, entry *entry.Entry) (int, error) {
|
|
return log.format(log.out, entry)
|
|
}
|
|
}
|
|
|
|
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()
|
|
|
|
return func(w io.Writer, entry *entry.Entry) (int, error) {
|
|
buf := buffer.New()
|
|
defer func() {
|
|
buf.Free()
|
|
}()
|
|
|
|
*buf = enc.AppendField(*buf, field.String(KeyMessage, entry.Message()))
|
|
|
|
for _, field := range entry.Fields() {
|
|
*buf = enc.AppendField(*buf, field)
|
|
}
|
|
|
|
_, _ = buf.WriteString("\n")
|
|
|
|
n, err := w.Write(*buf)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("format text:%w", err)
|
|
}
|
|
|
|
return n, nil
|
|
}
|
|
}
|
|
|
|
func formatJSON() func(w io.Writer, entry *entry.Entry) (int, error) {
|
|
enc := field.NewEncoderJSON()
|
|
|
|
return func(w io.Writer, entry *entry.Entry) (int, error) {
|
|
buf := buffer.New()
|
|
defer func() {
|
|
buf.Free()
|
|
}()
|
|
|
|
_, _ = buf.WriteString("{")
|
|
*buf = enc.AppendField(*buf, field.String(KeyMessage, entry.Message()))
|
|
|
|
for _, field := range entry.Fields() {
|
|
*buf = enc.AppendField(*buf, field)
|
|
}
|
|
|
|
_, _ = buf.WriteString("}")
|
|
_, _ = buf.WriteString("\n")
|
|
|
|
n, err := w.Write(*buf)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("format json:%w", err)
|
|
}
|
|
|
|
return n, nil
|
|
}
|
|
}
|
|
|