package slog import ( "bufio" "encoding/json" "fmt" "io" "os" "path/filepath" "strings" "time" ) type LoggerWriter interface { Close() error Write(p []byte) (n int, err error) Print(level LogLevel, prefix string, traceback []*MethodTraceback, messages ...any) error } type LoggerTextWriter struct { LoggerWriter writer io.Writer printTraceback bool printTime bool } func (w *LoggerTextWriter) Write(p []byte) (n int, err error) { n, err = w.writer.Write(p) if err != nil { return n, err } err = bufio.NewWriter(w.writer).Flush() return n, err } func (w *LoggerTextWriter) Print(level LogLevel, prefix string, _ []*MethodTraceback, messages ...any) error { s := BuildString(level, prefix, w.printTime, w.printTraceback, messages...) _, err := w.Write([]byte(s)) return err } func (w *LoggerTextWriter) Close() error { return w.writer.(io.Closer).Close() } // LoggerJsonWriter write into writer JSON type LoggerJsonWriter struct { LoggerWriter writer io.Writer pretty bool } type LoggerJsonMessage struct { Time time.Time `json:"time"` Level string `json:"level"` Prefix string `json:"prefix"` Message string `json:"message"` Traceback []*MethodTraceback `json:"traceback"` } func (w *LoggerJsonWriter) Write(data []byte) (int, error) { n, err := w.writer.Write(data) if err != nil { return n, err } err = bufio.NewWriter(w.writer).Flush() return n, err } func (w *LoggerJsonWriter) Print(level LogLevel, prefix string, traceback []*MethodTraceback, messages ...any) error { msg := Map(messages, func(el any) string { return fmt.Sprintf("%v", el) }) m := LoggerJsonMessage{ Time: time.Now(), Level: level.GetName(), Prefix: prefix, Message: strings.Join(msg, " "), Traceback: traceback, } var data []byte var err error if w.pretty { data, err = json.MarshalIndent(m, "", " ") } else { data, err = json.Marshal(m) } if err != nil { return err } _, err = w.Write(append(data, []byte("\n")...)) return err } func (w *LoggerJsonWriter) Close() error { return w.writer.(io.Closer).Close() } func CreateTextWriter(w io.Writer, printTraceback, printTime bool) *LoggerTextWriter { writer := &LoggerTextWriter{ writer: w, printTraceback: printTraceback, printTime: printTime, } return writer } func CreateTextFileWriter(path string, printTraceback, printTime bool) (*LoggerTextWriter, error) { err := os.MkdirAll(filepath.Dir(path), os.ModePerm) if err != nil { return nil, err } file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return nil, err } return CreateTextWriter(file, printTraceback, printTime), nil } func CreateTextStdoutWriter(printTraceback, printTime bool) *LoggerTextWriter { return CreateTextWriter(os.Stdout, printTraceback, printTime) } func CreateJsonWriter(w io.Writer, pretty bool) *LoggerJsonWriter { writer := &LoggerJsonWriter{ writer: w, pretty: pretty, } return writer } func CreateJsonStdoutWriter(pretty bool) *LoggerJsonWriter { return CreateJsonWriter(os.Stdout, pretty) } func CreateJsonFileWriter(path string, pretty bool) (*LoggerJsonWriter, error) { err := os.MkdirAll(filepath.Dir(path), os.ModePerm) if err != nil { return nil, err } file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return nil, err } return CreateJsonWriter(file, pretty), nil }