mirror of https://github.com/v2ray/v2ray-core
133 lines
2.3 KiB
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()))
|
|
}
|