| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 | package logimport (	"bytes"	"fmt"	"io"	"log"	"os"	"path/filepath"	"strings"	"sync"	"time")func NewFileWriter(tag, path string) io.Writer {	return &file{		Tag:  tag,		Path: path,	}}func NewLogger(w io.Writer, dept int) Logger {	return New(w, "", dept)}func New(w io.Writer, prefix string, dept int) *Log {	if prefix != "" {		prefix = buildPrefix(prefix) + " "	}	b := &Log{		Depth: dept,		log:   log.New(w, prefix, PrintFlags),	}	return b}const (	LevelError uint8 = iota	LevelWarn	LevelInfo	LevelDebug)const (	LevelsError = "[E]"	LevelsWarn  = "[W]"	LevelsInfo  = "[I]"	LevelsDebug = "[D]")const (	PrintFlags = log.LstdFlags | log.Llongfile)func buildPrefix(s string) string {	return "[" + strings.ToUpper(s) + "]"}func spitPrefix(s string) string {	idx := strings.Index(s, " ")	if idx == -1 {		return s	}	s = strings.ToLower(s[:idx])	s = strings.TrimPrefix(s, "[")	s = strings.TrimSuffix(s, "]")	return s}type file struct {	Tag  string // svc	Path string // /var/log	date string // 2006_01_02	fi   *os.File	mu   sync.Mutex}func (f *file) Write(b []byte) (n int, err error) {	f.mu.Lock()	defer f.mu.Unlock()	fi, err := f.open()	if err != nil {		return 0, err	}	return fi.Write(b)}func (f *file) statDir() error {	if _, err := os.Stat(f.Path); err != nil {		if os.IsNotExist(err) {			if err = os.MkdirAll(f.Path, os.ModePerm); err != nil {				return err			}		}		return err	}	return nil}func (f *file) openFile(name string) (*os.File, error) {	return os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, os.ModePerm) // 创建文件}func (f *file) name(date string) string {	// /var/log/svc_2006_01_02.log	return filepath.Join(f.Path, fmt.Sprintf("%s_%s.%s", f.Tag, date, ".log"))}func (f *file) open() (*os.File, error) {	if err := f.statDir(); err != nil {		return nil, err	}	date := time.Now().Format("2006_01_02")	name := f.name(date)	var (		fi  *os.File		err error	)	if _, err = os.Stat(name); err == nil { // 文件存在时		if date != f.date { // 如果保存的日期与当前日期不一致时			_ = f.fi.Close()			fi, err = f.openFile(name)			if err != nil {				return nil, err			}			f.fi = fi     // 更新文件句柄			f.date = date // 更新时间		} else {			fi = f.fi // 日期一致时		}		return fi, nil	}	if !os.IsNotExist(err) {		return nil, err	}	fi, err = f.openFile(name) // 创建文件	if err != nil {		return nil, err	}	f.fi = fi // 更新文件句柄	return fi, nil}type Log struct {	Depth int // 2	log   *log.Logger	mu    sync.Mutex}func (l *Log) Write(b []byte) (int, error) {	l.mu.Lock()	n, err := bytes.NewReader(b).WriteTo(l.log.Writer())	l.mu.Unlock()	return int(n), err}func (l *Log) WriteString(s string) (int, error) {	l.mu.Lock()	defer l.mu.Unlock()	err := l.log.Output(l.Depth, s)	if err != nil {		return 0, err	}	return len(s), nil}func (l *Log) Prefix(prefix string, f string, v ...any) {	l.mu.Lock()	old := l.log.Prefix()	l.setPrefixFmt(prefix)	_ = l.log.Output(l.Depth, fmt.Sprintf(f, v...))	l.setPrefixFmt(old)	l.mu.Unlock()}func (l *Log) Println(f string, v ...any) {	l.mu.Lock()	_ = l.log.Output(l.Depth, fmt.Sprintf(f, v...))	l.mu.Unlock()}// Logger startfunc (l *Log) Error(f string, v ...any) {	l.mu.Lock()	l.setPrefixFmt(LevelsError)	_ = l.log.Output(l.Depth, fmt.Sprintf(f, v...))	l.mu.Unlock()}func (l *Log) Warn(f string, v ...any) {	l.mu.Lock()	l.setPrefixFmt(LevelsWarn)	_ = l.log.Output(l.Depth, fmt.Sprintf(f, v...))	l.mu.Unlock()}func (l *Log) Info(f string, v ...any) {	l.mu.Lock()	l.setPrefixFmt(LevelsInfo)	_ = l.log.Output(l.Depth, fmt.Sprintf(f, v...))	l.mu.Unlock()}func (l *Log) Debug(f string, v ...any) {	l.mu.Lock()	l.setPrefixFmt(LevelsDebug)	_ = l.log.Output(l.Depth, fmt.Sprintf(f, v...))	l.mu.Unlock()}// Logger endfunc (l *Log) setPrefixFmt(s string) {	l.log.SetPrefix(s + " ")}
 |