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.

121 lines
2.2 KiB

package log
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"os"
)
const (
calldepth = 3
)
// New creates standart logger.
func New(opts ...Option) Logger {
logger := logger{
format: stringFormat,
output: log.Output,
calldepth: calldepth,
}
for _, opt := range opts {
opt(&logger)
}
return func(ctx context.Context, level Level, msg string, fields Fields) {
_ = logger.output(logger.calldepth, logger.format(msg, fields))
switch level {
case LevelEmergency:
panic(msg)
case LevelAlert:
os.Exit(1)
default:
}
}
}
// Option configure log.
type Option func(*logger)
// Format sets formats output message.
type Format func(msg string, fields Fields) string
type logger struct {
output func(calldepth int, s string) error
format Format
calldepth int
}
// WithWriter sets writer logger.
func WithWriter(writer io.Writer) Option {
return func(l *logger) {
l.output = log.New(writer, "", 0).Output
}
}
// WithStdout sets logged to os.Stdout.
func WithStdout() Option {
return func(l *logger) {
l.output = log.New(os.Stdout, "", 0).Output
}
}
// WithFormat sets format log.
func WithFormat(format Format) Option {
return func(l *logger) {
l.format = format
}
}
// WithStringFormat sets format as simple string.
func WithStringFormat() Option {
return func(l *logger) {
l.format = stringFormat
}
}
// WithJSONFormat sets json output format.
func WithJSONFormat() Option {
return func(l *logger) {
l.format = jsonFormat
}
}
// WithCalldepth sets depth filename.
func WithCalldepth(calldepth int) Option {
return func(l *logger) {
l.calldepth = calldepth
}
}
// WithLogger sets logger anf format.
func WithLogger(std *log.Logger, format Format) Option {
return func(l *logger) {
l.output = std.Output
l.format = format
}
}
func stringFormat(msg string, fields Fields) string {
return fmt.Sprint("msg=\"", msg, "\" ", fields)
}
func jsonFormat(msg string, fields Fields) string {
data := make(map[string]interface{}, len(fields)+1)
data["msg"] = msg
for _, field := range fields {
data[field.Key] = field.Value
}
res, err := json.Marshal(data)
if err != nil {
return stringFormat(msg, append(fields, FieldError(err)))
}
return string(res)
}