v2fly/common/log/logger.go

153 lines
2.9 KiB
Go
Raw Normal View History

2017-12-21 23:41:40 +00:00
package log
import (
"io"
"log"
"os"
"time"
2021-02-16 20:31:50 +00:00
"github.com/v2fly/v2ray-core/v4/common/platform"
"github.com/v2fly/v2ray-core/v4/common/signal/done"
"github.com/v2fly/v2ray-core/v4/common/signal/semaphore"
2017-12-21 23:41:40 +00:00
)
2017-12-22 09:44:13 +00:00
// Writer is the interface for writing logs.
type Writer interface {
2017-12-21 23:51:25 +00:00
Write(string) error
io.Closer
2017-12-21 23:41:40 +00:00
}
2017-12-22 09:44:13 +00:00
// WriterCreator is a function to create LogWriters.
type WriterCreator func() Writer
2017-12-21 23:41:40 +00:00
type generalLogger struct {
2017-12-22 09:44:13 +00:00
creator WriterCreator
2017-12-21 23:41:40 +00:00
buffer chan Message
2018-05-27 12:42:53 +00:00
access *semaphore.Instance
done *done.Instance
2017-12-21 23:41:40 +00:00
}
// NewLogger returns a generic log handler that can handle all type of messages.
2017-12-22 09:44:13 +00:00
func NewLogger(logWriterCreator WriterCreator) Handler {
2017-12-21 23:41:40 +00:00
return &generalLogger{
creator: logWriterCreator,
buffer: make(chan Message, 16),
2018-05-27 12:42:53 +00:00
access: semaphore.New(1),
done: done.New(),
2017-12-21 23:41:40 +00:00
}
}
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()
2017-12-21 23:41:40 +00:00
for {
select {
2018-04-15 18:40:47 +00:00
case <-l.done.Wait():
2018-02-14 16:35:09 +00:00
return
2017-12-21 23:41:40 +00:00
case msg := <-l.buffer:
logger.Write(msg.String() + platform.LineSeparator())
2017-12-21 23:41:40 +00:00
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:
}
}
2018-02-14 16:35:09 +00:00
func (l *generalLogger) Close() error {
return l.done.Close()
}
2017-12-21 23:41:40 +00:00
type consoleLogWriter struct {
logger *log.Logger
}
2017-12-21 23:51:25 +00:00
func (w *consoleLogWriter) Write(s string) error {
w.logger.Print(s)
return nil
2017-12-21 23:41:40 +00:00
}
func (w *consoleLogWriter) Close() error {
return nil
}
type fileLogWriter struct {
file *os.File
logger *log.Logger
}
2017-12-21 23:51:25 +00:00
func (w *fileLogWriter) Write(s string) error {
w.logger.Print(s)
return nil
2017-12-21 23:41:40 +00:00
}
func (w *fileLogWriter) Close() error {
return w.file.Close()
}
2017-12-22 09:41:10 +00:00
// CreateStdoutLogWriter returns a LogWriterCreator that creates LogWriter for stdout.
2017-12-22 09:44:13 +00:00
func CreateStdoutLogWriter() WriterCreator {
return func() Writer {
2017-12-21 23:41:40 +00:00
return &consoleLogWriter{
logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
}
}
}
2020-01-03 01:26:48 +00:00
// CreateStderrLogWriter returns a LogWriterCreator that creates LogWriter for stderr.
func CreateStderrLogWriter() WriterCreator {
return func() Writer {
return &consoleLogWriter{
logger: log.New(os.Stderr, "", log.Ldate|log.Ltime),
}
}
}
2017-12-22 09:41:10 +00:00
// CreateFileLogWriter returns a LogWriterCreator that creates LogWriter for the given file.
2017-12-22 09:44:13 +00:00
func CreateFileLogWriter(path string) (WriterCreator, error) {
2021-05-19 21:28:52 +00:00
file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)
2017-12-21 23:41:40 +00:00
if err != nil {
return nil, err
}
file.Close()
2017-12-22 09:44:13 +00:00
return func() Writer {
2021-05-19 21:28:52 +00:00
file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)
2017-12-21 23:41:40 +00:00
if err != nil {
return nil
}
return &fileLogWriter{
file: file,
logger: log.New(file, "", log.Ldate|log.Ltime),
}
}, nil
}
func init() {
RegisterHandler(NewLogger(CreateStdoutLogWriter()))
}