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.

146 lines
3.5 KiB

3 years ago
package log
import (
"context"
"fmt"
3 years ago
"os"
3 years ago
"runtime"
"time"
3 years ago
"gitoa.ru/go-4devs/log/entry"
"gitoa.ru/go-4devs/log/field"
"gitoa.ru/go-4devs/log/level"
3 years ago
)
// Middleware handle.
3 years ago
type Middleware func(ctx context.Context, e *entry.Entry, handler Logger) (int, error)
3 years ago
// With add middleware to logger.
func With(logger Logger, mw ...Middleware) Logger {
switch len(mw) {
case 0:
return logger
case 1:
3 years ago
return func(ctx context.Context, entry *entry.Entry) (int, error) {
return mw[0](ctx, entry, logger)
3 years ago
}
}
lastI := len(mw) - 1
2 years ago
return func(ctx context.Context, data *entry.Entry) (int, error) {
3 years ago
var (
3 years ago
chainHandler func(context.Context, *entry.Entry) (int, error)
3 years ago
curI int
)
3 years ago
chainHandler = func(currentCtx context.Context, currentEntry *entry.Entry) (int, error) {
3 years ago
if curI == lastI {
3 years ago
return logger(currentCtx, currentEntry)
3 years ago
}
3 years ago
curI++
3 years ago
n, err := mw[curI](currentCtx, currentEntry, chainHandler)
3 years ago
curI--
3 years ago
return n, err
3 years ago
}
2 years ago
return mw[0](ctx, data, chainHandler)
3 years ago
}
}
// WithLevel sets log level.
3 years ago
func WithLevel(key string, lvl level.Level) Middleware {
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
if e.Level().Enabled(lvl) {
return handler(ctx, e.AddString(key, e.Level().String()))
3 years ago
}
3 years ago
return 0, nil
3 years ago
}
}
// KeyValue add field by const key value.
func KeyValue(key string, value interface{}) Middleware {
3 years ago
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
return handler(ctx, e.AddAny(key, value))
3 years ago
}
}
// GoVersion add field by go version.
func GoVersion(key string) Middleware {
3 years ago
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
return handler(ctx, e.AddString(key, runtime.Version()))
3 years ago
}
}
// WithContext add field by context key.
func WithContextValue(keys ...fmt.Stringer) Middleware {
3 years ago
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
for _, key := range keys {
e = e.AddAny(key.String(), ctx.Value(key))
3 years ago
}
3 years ago
return handler(ctx, e)
3 years ago
}
}
func WithName(name string) Middleware {
return func(ctx context.Context, data *entry.Entry, handler Logger) (int, error) {
return handler(ctx, data.Replace(KeyName, field.StringValue(name)))
}
}
3 years ago
// WithCaller adds called file.
// Deprecated: use WithSource.
3 years ago
func WithCaller(key string, depth int, full bool) Middleware {
const offset = 2
3 years ago
3 years ago
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
return handler(ctx, e.AddString(key, entry.Caller(depth*offset, full)))
3 years ago
}
}
// WithTime adds time.
3 years ago
func WithTime(key, format string) Middleware {
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
return handler(ctx, e.Add(field.FormatTime(key, format, time.Now())))
3 years ago
}
}
// WithMetrics adds handle metrics.
3 years ago
func WithMetrics(metrics func(level level.Level)) Middleware {
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
go metrics(e.Level())
return handler(ctx, e)
}
}
// WithExit exit by level.
func WithExit(level level.Level) Middleware {
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
n, err := handler(ctx, e)
if e.Level().Is(level) {
os.Exit(1)
}
return n, err
}
}
// WithPanic panic by level.
func WithPanic(level level.Level) Middleware {
return func(ctx context.Context, e *entry.Entry, handler Logger) (int, error) {
n, err := handler(ctx, e)
if e.Level().Is(level) {
panic(e.String())
}
return n, err
3 years ago
}
}