logwriter/logwriter.go
2022-05-12 19:22:55 +05:00

147 lines
2.8 KiB
Go

package logwriter
import (
"bufio"
"bytes"
"fmt"
"io"
"time"
)
type LogWriter struct {
TimeFormat string
TimeZone *time.Location
writer io.Writer
newLine bool
}
// New created new LogWriter.
func New(w io.Writer) *LogWriter {
lw := &LogWriter{
TimeFormat: defaultTimeFormat,
TimeZone: defaultTimeZone,
writer: w,
newLine: true}
return lw
}
// Println formats using the default formats for its operands and writes to writer.
// Spaces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func (lw *LogWriter) Println(a ...any) (n int, err error) {
s := fmt.Sprintln(a...)
n, err = lw.Write([]byte(s))
if err != nil {
return n, err
}
lw.newLine = true
return n, nil
}
// Print formats using the default formats for its operands and writes to writer.
// Spaces are added between operands when neither is a string.
// It returns the number of bytes written and any write error encountered.
func (lw *LogWriter) Print(a ...any) (n int, err error) {
s := fmt.Sprint(a...)
n, err = lw.Write([]byte(s))
if err != nil {
return n, err
}
if s[len(s)-1] == '\n' {
lw.newLine = true
} else {
lw.newLine = false
}
return n, nil
}
// Printf formats according to a format specifier and writes to writer.
// It returns the number of bytes written and any write error encountered.
func (lw *LogWriter) Printf(format string, a ...any) (n int, err error) {
s := fmt.Sprintf(format, a...)
n, err = lw.Write([]byte(s))
if err != nil {
return n, err
}
if s[len(s)-1] == '\n' {
lw.newLine = true
} else {
lw.newLine = false
}
return n, nil
}
// Write writes len(p) bytes from p to the writer.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
func (lw *LogWriter) Write(p []byte) (n int, err error) {
r := bufio.NewReader(bytes.NewReader(p))
for {
line, err := r.ReadString('\n')
if err == io.EOF && len(line) > 0 {
nn, err := io.WriteString(lw.writer, lw.prefix()+" "+line)
n += nn
if err != nil {
return n, err
}
if line[len(line)-1] == '\n' {
lw.newLine = true // TODO: uncovered or unused?
} else {
lw.newLine = false
}
break
}
if err == io.EOF {
break
}
if lw.newLine {
nn, err := io.WriteString(lw.writer, lw.prefix()+" "+line)
n += nn
if err != nil {
return n, err
}
} else {
nn, err := io.WriteString(lw.writer, line)
n += nn
if err != nil {
return n, err
}
lw.newLine = true
}
}
return n, nil
}
func (lw *LogWriter) Close() error {
if lw.newLine {
return nil
}
_, err := io.WriteString(lw, "\n")
if err != nil {
return err
}
lw.newLine = true
return nil
}
func (lw *LogWriter) prefix() string {
return fmt.Sprintf("%s", time.Now().Format(lw.TimeFormat))
}