v2ray-core/common/log/logger.go

133 lines
2.3 KiB
Go

package log
import (
"io"
"log"
"os"
"time"
"v2ray.com/core/common/platform"
"v2ray.com/core/common/signal"
)
type LogWriter interface {
io.WriteCloser
}
type LogWriterCreator func() LogWriter
type generalLogger struct {
creator LogWriterCreator
buffer chan Message
access *signal.Semaphore
}
// NewLogger returns a generic log handler that can handle all type of messages.
func NewLogger(logWriterCreator LogWriterCreator) Handler {
return &generalLogger{
creator: logWriterCreator,
buffer: make(chan Message, 16),
access: signal.NewSemaphore(1),
}
}
func (l *generalLogger) run() {
defer l.access.Signal()
dataWritten := false
ticker := time.NewTicker(time.Minute)
defer ticker.Stop()
logger := l.creator()
if logger == nil {
return
}
defer logger.Close()
ls := []byte(platform.LineSeparator())
for {
select {
case msg := <-l.buffer:
logger.Write([]byte(msg.String()))
logger.Write(ls)
dataWritten = true
case <-ticker.C:
if !dataWritten {
return
}
dataWritten = false
}
}
}
func (l *generalLogger) Handle(msg Message) {
select {
case l.buffer <- msg:
default:
}
select {
case <-l.access.Wait():
go l.run()
default:
}
}
type consoleLogWriter struct {
logger *log.Logger
}
func (w *consoleLogWriter) Write(b []byte) (int, error) {
w.logger.Print(string(b))
return len(b), nil
}
func (w *consoleLogWriter) Close() error {
return nil
}
type fileLogWriter struct {
file *os.File
logger *log.Logger
}
func (w *fileLogWriter) Write(b []byte) (int, error) {
w.logger.Print(string(b))
return len(b), nil
}
func (w *fileLogWriter) Close() error {
return w.file.Close()
}
func CreateStdoutLogWriter() LogWriterCreator {
return func() LogWriter {
return &consoleLogWriter{
logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
}
}
}
func CreateFileLogWriter(path string) (LogWriterCreator, error) {
file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return nil, err
}
file.Close()
return func() LogWriter {
file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return nil
}
return &fileLogWriter{
file: file,
logger: log.New(file, "", log.Ldate|log.Ltime),
}
}, nil
}
func init() {
RegisterHandler(NewLogger(CreateStdoutLogWriter()))
}