1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-22 10:08:15 -05:00

reorg common/log

This commit is contained in:
v2ray 2016-05-11 23:24:41 -07:00
parent a37819c330
commit abdcda0a2f
9 changed files with 145 additions and 193 deletions

View File

@ -1,8 +1,9 @@
package alloc package alloc_test
import ( import (
"testing" "testing"
. "github.com/v2ray/v2ray-core/common/alloc"
v2testing "github.com/v2ray/v2ray-core/testing" v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert" "github.com/v2ray/v2ray-core/testing/assert"
) )

View File

@ -1,7 +1,7 @@
package log package log
import ( import (
"github.com/v2ray/v2ray-core/common/alloc" "github.com/v2ray/v2ray-core/common/log/internal"
"github.com/v2ray/v2ray-core/common/serial" "github.com/v2ray/v2ray-core/common/serial"
) )
@ -14,32 +14,12 @@ const (
) )
var ( var (
accessLoggerInstance logWriter = &noOpLogWriter{} accessLoggerInstance internal.LogWriter = new(internal.NoOpLogWriter)
) )
type accessLog struct {
From serial.String
To serial.String
Status AccessStatus
Reason serial.String
}
func (this *accessLog) Release() {
this.From = nil
this.To = nil
this.Reason = nil
}
func (this *accessLog) String() string {
b := alloc.NewSmallBuffer().Clear()
defer b.Release()
return b.AppendString(this.From.String()).AppendString(" ").AppendString(string(this.Status)).AppendString(" ").AppendString(this.To.String()).AppendString(" ").AppendString(this.Reason.String()).String()
}
// InitAccessLogger initializes the access logger to write into the give file. // InitAccessLogger initializes the access logger to write into the give file.
func InitAccessLogger(file string) error { func InitAccessLogger(file string) error {
logger, err := newFileLogWriter(file) logger, err := internal.NewFileLogWriter(file)
if err != nil { if err != nil {
Error("Failed to create access logger on file (", file, "): ", file, err) Error("Failed to create access logger on file (", file, "): ", file, err)
return err return err
@ -50,10 +30,10 @@ func InitAccessLogger(file string) error {
// Access writes an access log. // Access writes an access log.
func Access(from, to serial.String, status AccessStatus, reason serial.String) { func Access(from, to serial.String, status AccessStatus, reason serial.String) {
accessLoggerInstance.Log(&accessLog{ accessLoggerInstance.Log(&internal.AccessLog{
From: from, From: from,
To: to, To: to,
Status: status, Status: string(status),
Reason: reason, Reason: reason,
}) })
} }

View File

@ -1,36 +0,0 @@
package log
import (
"io/ioutil"
"os"
"testing"
"time"
"github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestAccessLog(t *testing.T) {
v2testing.Current(t)
filename := "/tmp/test_access_log.log"
InitAccessLogger(filename)
_, err := os.Stat(filename)
assert.Error(err).IsNil()
Access(serial.StringLiteral("test_from"), serial.StringLiteral("test_to"), AccessAccepted, serial.StringLiteral("test_reason"))
<-time.After(2 * time.Second)
accessLoggerInstance.(*fileLogWriter).close()
accessLoggerInstance = &noOpLogWriter{}
content, err := ioutil.ReadFile(filename)
assert.Error(err).IsNil()
contentStr := serial.StringLiteral(content)
assert.String(contentStr).Contains(serial.StringLiteral("test_from"))
assert.String(contentStr).Contains(serial.StringLiteral("test_to"))
assert.String(contentStr).Contains(serial.StringLiteral("test_reason"))
assert.String(contentStr).Contains(serial.StringLiteral("accepted"))
}

View File

@ -0,0 +1,69 @@
package internal
import (
"fmt"
"github.com/v2ray/v2ray-core/common"
"github.com/v2ray/v2ray-core/common/alloc"
"github.com/v2ray/v2ray-core/common/serial"
)
type LogEntry interface {
common.Releasable
serial.String
}
type ErrorLog struct {
Prefix string
Values []interface{}
}
func (this *ErrorLog) Release() {
for index := range this.Values {
this.Values[index] = nil
}
this.Values = nil
}
func (this *ErrorLog) String() string {
b := alloc.NewSmallBuffer().Clear()
defer b.Release()
b.AppendString(this.Prefix)
for _, value := range this.Values {
switch typedVal := value.(type) {
case string:
b.AppendString(typedVal)
case *string:
b.AppendString(*typedVal)
case serial.String:
b.AppendString(typedVal.String())
case error:
b.AppendString(typedVal.Error())
default:
b.AppendString(fmt.Sprint(value))
}
}
return b.String()
}
type AccessLog struct {
From serial.String
To serial.String
Status string
Reason serial.String
}
func (this *AccessLog) Release() {
this.From = nil
this.To = nil
this.Reason = nil
}
func (this *AccessLog) String() string {
b := alloc.NewSmallBuffer().Clear()
defer b.Release()
return b.AppendString(this.From.String()).AppendString(" ").AppendString(this.Status).AppendString(" ").AppendString(this.To.String()).AppendString(" ").AppendString(this.Reason.String()).String()
}

View File

@ -0,0 +1,27 @@
package internal_test
import (
"testing"
. "github.com/v2ray/v2ray-core/common/log/internal"
"github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestAccessLog(t *testing.T) {
v2testing.Current(t)
entry := &AccessLog{
From: serial.StringLiteral("test_from"),
To: serial.StringLiteral("test_to"),
Status: "Accepted",
Reason: serial.StringLiteral("test_reason"),
}
entryStr := entry.String()
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("test_from"))
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("test_to"))
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("test_reason"))
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("Accepted"))
}

View File

@ -1,50 +1,45 @@
package log package internal
import ( import (
"io"
"log" "log"
"os" "os"
"github.com/v2ray/v2ray-core/common/platform" "github.com/v2ray/v2ray-core/common/platform"
) )
func createLogger(writer io.Writer) *log.Logger { type LogWriter interface {
return log.New(writer, "", log.Ldate|log.Ltime)
}
type logWriter interface {
Log(LogEntry) Log(LogEntry)
} }
type noOpLogWriter struct { type NoOpLogWriter struct {
} }
func (this *noOpLogWriter) Log(entry LogEntry) { func (this *NoOpLogWriter) Log(entry LogEntry) {
entry.Release() entry.Release()
} }
type stdOutLogWriter struct { type StdOutLogWriter struct {
logger *log.Logger logger *log.Logger
} }
func newStdOutLogWriter() logWriter { func NewStdOutLogWriter() LogWriter {
return &stdOutLogWriter{ return &StdOutLogWriter{
logger: createLogger(os.Stdout), logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
} }
} }
func (this *stdOutLogWriter) Log(log LogEntry) { func (this *StdOutLogWriter) Log(log LogEntry) {
this.logger.Print(log.String() + platform.LineSeparator()) this.logger.Print(log.String() + platform.LineSeparator())
log.Release() log.Release()
} }
type fileLogWriter struct { type FileLogWriter struct {
queue chan LogEntry queue chan LogEntry
logger *log.Logger logger *log.Logger
file *os.File file *os.File
} }
func (this *fileLogWriter) Log(log LogEntry) { func (this *FileLogWriter) Log(log LogEntry) {
select { select {
case this.queue <- log: case this.queue <- log:
default: default:
@ -53,7 +48,7 @@ func (this *fileLogWriter) Log(log LogEntry) {
} }
} }
func (this *fileLogWriter) run() { func (this *FileLogWriter) run() {
for { for {
entry, open := <-this.queue entry, open := <-this.queue
if !open { if !open {
@ -65,16 +60,16 @@ func (this *fileLogWriter) run() {
} }
} }
func (this *fileLogWriter) close() { func (this *FileLogWriter) Close() {
this.file.Close() this.file.Close()
} }
func newFileLogWriter(path string) (*fileLogWriter, error) { func NewFileLogWriter(path string) (*FileLogWriter, error) {
file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil { if err != nil {
return nil, err return nil, err
} }
logger := &fileLogWriter{ logger := &FileLogWriter{
queue: make(chan LogEntry, 16), queue: make(chan LogEntry, 16),
logger: log.New(file, "", log.Ldate|log.Ltime), logger: log.New(file, "", log.Ldate|log.Ltime),
file: file, file: file,

View File

@ -0,0 +1 @@
package internal_test

View File

@ -1,13 +1,11 @@
package log package log
import ( import (
"fmt" "github.com/v2ray/v2ray-core/common/log/internal"
"github.com/v2ray/v2ray-core/common"
"github.com/v2ray/v2ray-core/common/alloc"
"github.com/v2ray/v2ray-core/common/serial"
) )
type LogLevel int
const ( const (
DebugLevel = LogLevel(0) DebugLevel = LogLevel(0)
InfoLevel = LogLevel(1) InfoLevel = LogLevel(1)
@ -16,86 +14,43 @@ const (
NoneLevel = LogLevel(999) NoneLevel = LogLevel(999)
) )
type LogEntry interface {
common.Releasable
serial.String
}
type errorLog struct {
prefix string
values []interface{}
}
func (this *errorLog) Release() {
for index := range this.values {
this.values[index] = nil
}
this.values = nil
}
func (this *errorLog) String() string {
b := alloc.NewSmallBuffer().Clear()
defer b.Release()
b.AppendString(this.prefix)
for _, value := range this.values {
switch typedVal := value.(type) {
case string:
b.AppendString(typedVal)
case *string:
b.AppendString(*typedVal)
case serial.String:
b.AppendString(typedVal.String())
case error:
b.AppendString(typedVal.Error())
default:
b.AppendString(fmt.Sprint(value))
}
}
return b.String()
}
var ( var (
noOpLoggerInstance logWriter = &noOpLogWriter{} streamLoggerInstance internal.LogWriter = internal.NewStdOutLogWriter()
streamLoggerInstance logWriter = newStdOutLogWriter()
debugLogger = noOpLoggerInstance debugLogger internal.LogWriter = streamLoggerInstance
infoLogger = noOpLoggerInstance infoLogger internal.LogWriter = streamLoggerInstance
warningLogger = streamLoggerInstance warningLogger internal.LogWriter = streamLoggerInstance
errorLogger = streamLoggerInstance errorLogger internal.LogWriter = streamLoggerInstance
) )
type LogLevel int
func SetLogLevel(level LogLevel) { func SetLogLevel(level LogLevel) {
debugLogger = noOpLoggerInstance debugLogger = new(internal.NoOpLogWriter)
if level <= DebugLevel { if level <= DebugLevel {
debugLogger = streamLoggerInstance debugLogger = streamLoggerInstance
} }
infoLogger = noOpLoggerInstance infoLogger = new(internal.NoOpLogWriter)
if level <= InfoLevel { if level <= InfoLevel {
infoLogger = streamLoggerInstance infoLogger = streamLoggerInstance
} }
warningLogger = noOpLoggerInstance warningLogger = new(internal.NoOpLogWriter)
if level <= WarningLevel { if level <= WarningLevel {
warningLogger = streamLoggerInstance warningLogger = streamLoggerInstance
} }
errorLogger = noOpLoggerInstance errorLogger = new(internal.NoOpLogWriter)
if level <= ErrorLevel { if level <= ErrorLevel {
errorLogger = streamLoggerInstance errorLogger = streamLoggerInstance
} }
if level == NoneLevel { if level == NoneLevel {
accessLoggerInstance = noOpLoggerInstance accessLoggerInstance = new(internal.NoOpLogWriter)
} }
} }
func InitErrorLogger(file string) error { func InitErrorLogger(file string) error {
logger, err := newFileLogWriter(file) logger, err := internal.NewFileLogWriter(file)
if err != nil { if err != nil {
Error("Failed to create error logger on file (", file, "): ", err) Error("Failed to create error logger on file (", file, "): ", err)
return err return err
@ -106,32 +61,32 @@ func InitErrorLogger(file string) error {
// Debug outputs a debug log with given format and optional arguments. // Debug outputs a debug log with given format and optional arguments.
func Debug(v ...interface{}) { func Debug(v ...interface{}) {
debugLogger.Log(&errorLog{ debugLogger.Log(&internal.ErrorLog{
prefix: "[Debug]", Prefix: "[Debug]",
values: v, Values: v,
}) })
} }
// Info outputs an info log with given format and optional arguments. // Info outputs an info log with given format and optional arguments.
func Info(v ...interface{}) { func Info(v ...interface{}) {
infoLogger.Log(&errorLog{ infoLogger.Log(&internal.ErrorLog{
prefix: "[Info]", Prefix: "[Info]",
values: v, Values: v,
}) })
} }
// Warning outputs a warning log with given format and optional arguments. // Warning outputs a warning log with given format and optional arguments.
func Warning(v ...interface{}) { func Warning(v ...interface{}) {
warningLogger.Log(&errorLog{ warningLogger.Log(&internal.ErrorLog{
prefix: "[Warning]", Prefix: "[Warning]",
values: v, Values: v,
}) })
} }
// Error outputs an error log with given format and optional arguments. // Error outputs an error log with given format and optional arguments.
func Error(v ...interface{}) { func Error(v ...interface{}) {
errorLogger.Log(&errorLog{ errorLogger.Log(&internal.ErrorLog{
prefix: "[Error]", Prefix: "[Error]",
values: v, Values: v,
}) })
} }

View File

@ -1,40 +0,0 @@
package log
import (
"bytes"
"log"
"testing"
"github.com/v2ray/v2ray-core/common/platform"
"github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestLogLevelSetting(t *testing.T) {
v2testing.Current(t)
assert.Pointer(debugLogger).Equals(noOpLoggerInstance)
SetLogLevel(DebugLevel)
assert.Pointer(debugLogger).Equals(streamLoggerInstance)
SetLogLevel(InfoLevel)
assert.Pointer(debugLogger).Equals(noOpLoggerInstance)
assert.Pointer(infoLogger).Equals(streamLoggerInstance)
}
func TestStreamLogger(t *testing.T) {
v2testing.Current(t)
buffer := bytes.NewBuffer(make([]byte, 0, 1024))
infoLogger = &stdOutLogWriter{
logger: log.New(buffer, "", 0),
}
Info("Test ", "Stream Logger", " Format")
assert.StringLiteral(string(buffer.Bytes())).Equals("[Info]Test Stream Logger Format" + platform.LineSeparator())
buffer.Reset()
errorLogger = infoLogger
Error("Test ", serial.StringLiteral("literal"), " Format")
assert.StringLiteral(string(buffer.Bytes())).Equals("[Error]Test literal Format" + platform.LineSeparator())
}