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.
122 lines
2.2 KiB
122 lines
2.2 KiB
3 years ago
|
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)
|
||
|
}
|