mirror of https://github.com/dnomd343/XProxy.git
Dnomd343
11 months ago
17 changed files with 572 additions and 198 deletions
@ -1,7 +1,7 @@ |
|||
package assets |
|||
|
|||
import ( |
|||
"XProxy/next/logger" |
|||
"XProxy/logger" |
|||
"github.com/robfig/cron" |
|||
urlpkg "net/url" |
|||
"os" |
@ -1,7 +1,7 @@ |
|||
package assets |
|||
|
|||
import ( |
|||
"XProxy/next/logger" |
|||
"XProxy/logger" |
|||
"bytes" |
|||
"compress/bzip2" |
|||
"github.com/gabriel-vasile/mimetype" |
@ -1,7 +1,7 @@ |
|||
package assets |
|||
|
|||
import ( |
|||
"XProxy/next/logger" |
|||
"XProxy/logger" |
|||
"bytes" |
|||
"errors" |
|||
"github.com/andybalholm/brotli" |
@ -1,7 +1,7 @@ |
|||
package assets |
|||
|
|||
import ( |
|||
"XProxy/next/logger" |
|||
"XProxy/logger" |
|||
urlpkg "net/url" |
|||
"os" |
|||
"path" |
@ -0,0 +1,99 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"XProxy/mocks" |
|||
"fmt" |
|||
"github.com/magiconair/properties/assert" |
|||
"github.com/petermattis/goid" |
|||
"github.com/stretchr/testify/mock" |
|||
"go.uber.org/zap/zapcore" |
|||
"runtime" |
|||
"strings" |
|||
"testing" |
|||
"time" |
|||
) |
|||
|
|||
var testTime = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) |
|||
|
|||
// zapCaller build fake caller with the absolute path of current code.
|
|||
func zapCaller() zapcore.EntryCaller { |
|||
_, srcPath, _, _ := runtime.Caller(0) |
|||
return zapcore.EntryCaller{ |
|||
File: srcPath, |
|||
Line: 0, |
|||
} |
|||
} |
|||
|
|||
// encoderTest is a helper function to test buffer output of mock encoder.
|
|||
func encoderTest(t *testing.T, exec func(*mocks.PrimitiveArrayEncoder), expect string) { |
|||
encoder := mocks.NewPrimitiveArrayEncoder(t) |
|||
encoder.On("AppendInt64", mock.Anything).Maybe() // only enroll used method
|
|||
encoder.On("AppendString", mock.Anything).Maybe() |
|||
|
|||
exec(encoder) |
|||
var values []string |
|||
for _, call := range encoder.Calls { |
|||
values = append(values, fmt.Sprintf("%v", call.Arguments.Get(0))) |
|||
} |
|||
assert.Equal(t, strings.Join(values, " "), expect) |
|||
} |
|||
|
|||
func Test_getCaller(t *testing.T) { |
|||
caller := zapCaller() |
|||
caller.File = "Invalid Path" |
|||
assert.Equal(t, getCaller(caller, true), "unknown") |
|||
assert.Equal(t, getCaller(caller, false), "unknown") |
|||
|
|||
assert.Equal(t, getCaller(zapCaller(), false), "logger/encoder_test") |
|||
assert.Equal(t, getCaller(zapCaller(), true), "logger/encoder_test.go:0") |
|||
} |
|||
|
|||
func Test_timeEncoder(t *testing.T) { |
|||
encoderTest(t, func(encoder *mocks.PrimitiveArrayEncoder) { |
|||
timeEncoder(testTime, encoder) |
|||
}, "2000-01-01 00:00:00.000") |
|||
|
|||
encoderTest(t, func(encoder *mocks.PrimitiveArrayEncoder) { |
|||
timeColoredEncoder(testTime, encoder) |
|||
}, "\x1b[36m"+logger.prefix+"\x1b[0m \x1b[90m2000-01-01 00:00:00.000\x1b[0m") |
|||
} |
|||
|
|||
func Test_callerEncoder(t *testing.T) { |
|||
verboseVal := logger.verbose |
|||
callerTest := func(entry func(zapcore.EntryCaller, zapcore.PrimitiveArrayEncoder), expect string) { |
|||
encoderTest(t, func(encoder *mocks.PrimitiveArrayEncoder) { |
|||
entry(zapCaller(), encoder) |
|||
}, expect) |
|||
} |
|||
|
|||
logger.verbose = false |
|||
callerTest(callerEncoder, "[logger/encoder_test]") |
|||
callerTest(callerColoredEncoder, "\x1b[35m[logger/encoder_test]\x1b[0m") |
|||
|
|||
logger.verbose = true |
|||
gid := fmt.Sprintf("[%d]", goid.Get()) |
|||
callerTest(callerEncoder, gid+" [logger/encoder_test.go:0]") |
|||
callerTest(callerColoredEncoder, "\x1b[34m"+gid+"\x1b[0m \x1b[35m[logger/encoder_test.go:0]\x1b[0m") |
|||
|
|||
logger.verbose = verboseVal |
|||
} |
|||
|
|||
func Test_levelEncoder(t *testing.T) { |
|||
levelTest := func(entry func(zapcore.Level, zapcore.PrimitiveArrayEncoder), level zapcore.Level, expect string) { |
|||
encoderTest(t, func(encoder *mocks.PrimitiveArrayEncoder) { |
|||
entry(level, encoder) |
|||
}, expect) |
|||
} |
|||
|
|||
levelTest(levelEncoder, zapcore.DebugLevel, "[DEBUG]") |
|||
levelTest(levelEncoder, zapcore.InfoLevel, "[INFO]") |
|||
levelTest(levelEncoder, zapcore.WarnLevel, "[WARN]") |
|||
levelTest(levelEncoder, zapcore.ErrorLevel, "[ERROR]") |
|||
levelTest(levelEncoder, zapcore.PanicLevel, "[PANIC]") |
|||
|
|||
levelTest(levelColoredEncoder, zapcore.DebugLevel, "\x1b[39m[DEBUG]\x1b[0m") |
|||
levelTest(levelColoredEncoder, zapcore.InfoLevel, "\x1b[32m[INFO]\x1b[0m") |
|||
levelTest(levelColoredEncoder, zapcore.WarnLevel, "\x1b[33m[WARN]\x1b[0m") |
|||
levelTest(levelColoredEncoder, zapcore.ErrorLevel, "\x1b[31m[ERROR]\x1b[0m") |
|||
levelTest(levelColoredEncoder, zapcore.PanicLevel, "\x1b[91m[PANIC]\x1b[0m") |
|||
} |
@ -0,0 +1,65 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"go.uber.org/zap/zapcore" |
|||
"io" |
|||
) |
|||
|
|||
type Level = zapcore.Level |
|||
|
|||
const ( |
|||
DebugLevel = zapcore.DebugLevel |
|||
InfoLevel = zapcore.InfoLevel |
|||
WarnLevel = zapcore.WarnLevel |
|||
ErrorLevel = zapcore.ErrorLevel |
|||
PanicLevel = zapcore.PanicLevel |
|||
) |
|||
|
|||
func Debugf(template string, args ...interface{}) { |
|||
logger.entry.Debugf(template, args...) |
|||
} |
|||
|
|||
func Infof(template string, args ...interface{}) { |
|||
logger.entry.Infof(template, args...) |
|||
} |
|||
|
|||
func Warnf(template string, args ...interface{}) { |
|||
logger.entry.Warnf(template, args...) |
|||
} |
|||
|
|||
func Errorf(template string, args ...interface{}) { |
|||
logger.entry.Errorf(template, args...) |
|||
} |
|||
|
|||
func Panicf(template string, args ...interface{}) { |
|||
logger.entry.Panicf(template, args...) |
|||
} |
|||
|
|||
// GetLevel return the current logger level.
|
|||
func GetLevel() Level { |
|||
return logger.level.Level() |
|||
} |
|||
|
|||
// SetLevel configure logger output level. Note that debug level will output
|
|||
// more information and reduce performance.
|
|||
func SetLevel(level Level) { |
|||
logger.level.SetLevel(level) |
|||
if level == DebugLevel { |
|||
logger.verbose = true |
|||
} else { |
|||
logger.verbose = false |
|||
} |
|||
} |
|||
|
|||
// AddWriters add more writers to target log channel.
|
|||
func AddWriters(colored bool, writers ...io.Writer) { |
|||
var syncWriters []zapcore.WriteSyncer |
|||
for _, writer := range writers { |
|||
syncWriters = append(syncWriters, zapcore.AddSync(writer)) |
|||
} |
|||
if !colored { |
|||
logger.addPlainWrites(syncWriters...) |
|||
} else { |
|||
logger.addColoredWrites(syncWriters...) |
|||
} |
|||
} |
@ -0,0 +1,101 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"bytes" |
|||
"github.com/stretchr/testify/assert" |
|||
"go.uber.org/zap" |
|||
"go.uber.org/zap/zapcore" |
|||
"os" |
|||
"regexp" |
|||
"strings" |
|||
"testing" |
|||
) |
|||
|
|||
var Levels = []Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, PanicLevel} |
|||
|
|||
func Test_level(t *testing.T) { |
|||
assert.Equal(t, DebugLevel, zap.DebugLevel) |
|||
assert.Equal(t, InfoLevel, zap.InfoLevel) |
|||
assert.Equal(t, WarnLevel, zap.WarnLevel) |
|||
assert.Equal(t, ErrorLevel, zap.ErrorLevel) |
|||
assert.Equal(t, PanicLevel, zap.PanicLevel) |
|||
|
|||
for _, level := range Levels { |
|||
SetLevel(level) |
|||
assert.Equal(t, GetLevel(), level) |
|||
assert.Equal(t, logger.verbose, level == DebugLevel) // verbose only for DEBUG level
|
|||
} |
|||
SetLevel(InfoLevel) // revert to INFO level
|
|||
} |
|||
|
|||
func Test_logger(t *testing.T) { |
|||
var plainBuf, plainTeeBuf bytes.Buffer |
|||
var coloredBuf, coloredTeeBuf bytes.Buffer |
|||
logger.plain.writers = []zapcore.WriteSyncer{} // clear slice
|
|||
logger.colored.writers = []zapcore.WriteSyncer{} |
|||
AddWriters(false, &plainBuf, &plainTeeBuf) |
|||
AddWriters(true, &coloredBuf, &coloredTeeBuf) |
|||
logger.update() // apply test writers
|
|||
|
|||
printLogs := func(usingLevel Level) { |
|||
SetLevel(usingLevel) |
|||
Debugf("Here is %s level", "DEBUG") |
|||
Infof("Here is %s level", "INFO") |
|||
Warnf("Here is %s level", "WARN") |
|||
Errorf("Here is %s level", "ERROR") |
|||
assert.Panics(t, func() { |
|||
Panicf("Here is %s level", "PANIC") |
|||
}) |
|||
} |
|||
printLogs(DebugLevel) // output into buffer
|
|||
printLogs(InfoLevel) |
|||
printLogs(WarnLevel) |
|||
printLogs(ErrorLevel) |
|||
printLogs(PanicLevel) |
|||
|
|||
assertLine := func(log string, level Level, colored bool, verbose bool) { |
|||
regex := `^([\d.:\- ]+) \[(\S+)] (\[\d+] )?\[(\S+)] Here is (\S+) level$` |
|||
if colored { |
|||
regex = `^\x1b\[36m\[XProxy]\x1b\[0m \x1b\[90m([\d.:\- ]+)\x1b\[0m ` + |
|||
`\x1b\[\d\dm\[(\S+)]\x1b\[0m (\x1b\[34m\[\d+]\x1b\[0m )?` + |
|||
`\x1b\[35m\[(\S+)]\x1b\[0m Here is (\S+) level$` |
|||
} |
|||
matches := regexp.MustCompile(regex).FindStringSubmatch(log) |
|||
timeRegex := regexp.MustCompile(`^\d{4}(-\d\d){2} \d{2}(:\d\d){2}\.\d{3}$`) |
|||
|
|||
assert.NotEmpty(t, matches) // valid log line
|
|||
assert.Regexp(t, timeRegex, matches[1]) // valid time format
|
|||
assert.Equal(t, level.CapitalString(), matches[2]) // valid level string
|
|||
assert.Equal(t, level.CapitalString(), matches[5]) |
|||
if !verbose { |
|||
assert.Equal(t, "logger/interface_test", matches[4]) |
|||
} else { |
|||
assert.Regexp(t, regexp.MustCompile(`^logger/interface_test.go:\d+$`), matches[4]) |
|||
} |
|||
} |
|||
|
|||
assertLogs := func(buffer string, colored bool) { |
|||
var line string |
|||
logs := strings.Split(buffer, "\n") |
|||
for _, limit := range Levels { |
|||
for _, level := range Levels { |
|||
if level >= limit { |
|||
line, logs = logs[0], logs[1:] |
|||
assertLine(line, level, colored, limit == DebugLevel) |
|||
} |
|||
} |
|||
} |
|||
assert.Equal(t, len(logs), 1) |
|||
assert.Equal(t, logs[0], "") // last line is empty
|
|||
} |
|||
|
|||
assertLogs(plainBuf.String(), false) |
|||
assertLogs(coloredBuf.String(), true) |
|||
assert.Equal(t, plainBuf.String(), plainTeeBuf.String()) |
|||
assert.Equal(t, coloredBuf.String(), coloredTeeBuf.String()) |
|||
|
|||
logger.plain.writers = []zapcore.WriteSyncer{} // revert logger configure
|
|||
logger.colored.writers = []zapcore.WriteSyncer{os.Stdout} |
|||
logger.level.SetLevel(InfoLevel) |
|||
logger.update() |
|||
} |
@ -0,0 +1,95 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"go.uber.org/zap" |
|||
"go.uber.org/zap/zapcore" |
|||
"os" |
|||
"path" |
|||
"runtime" |
|||
) |
|||
|
|||
var project string // project absolute path
|
|||
var logger *logCore // singleton logger handle
|
|||
|
|||
// logChannel handle multiple writers with unified format.
|
|||
type logChannel struct { |
|||
encoder zapcore.Encoder |
|||
writers []zapcore.WriteSyncer |
|||
} |
|||
|
|||
// logCore manage log level, channels and other interfaces.
|
|||
type logCore struct { |
|||
prefix string // custom output prefix
|
|||
verbose bool // show verbose information
|
|||
|
|||
plain logChannel // log channel with plain text
|
|||
colored logChannel // log channel with colored text
|
|||
|
|||
level *zap.AtomicLevel // zap log level pointer
|
|||
entry *zap.SugaredLogger // zap sugared logger entry
|
|||
} |
|||
|
|||
func init() { |
|||
_, src, _, _ := runtime.Caller(0) // absolute path of current code
|
|||
project = path.Join(path.Dir(src), "../") |
|||
|
|||
zapLevel := zap.NewAtomicLevelAt(InfoLevel) // using info level in default
|
|||
logger = &logCore{ |
|||
verbose: false, |
|||
level: &zapLevel, |
|||
prefix: "[XProxy]", |
|||
plain: buildChannel(false), |
|||
colored: buildChannel(true), |
|||
} |
|||
logger.addColoredWrites(os.Stderr) // output into stderr in default
|
|||
} |
|||
|
|||
// buildChannel generate logChannel with `colored` option.
|
|||
func buildChannel(colored bool) logChannel { |
|||
config := zapcore.EncoderConfig{ |
|||
ConsoleSeparator: " ", |
|||
MessageKey: "msg", |
|||
LevelKey: "level", |
|||
TimeKey: "time", |
|||
CallerKey: "caller", |
|||
EncodeTime: timeEncoder, |
|||
EncodeLevel: levelEncoder, |
|||
EncodeCaller: callerEncoder, |
|||
} |
|||
if colored { // using colored version
|
|||
config.EncodeTime = timeColoredEncoder |
|||
config.EncodeLevel = levelColoredEncoder |
|||
config.EncodeCaller = callerColoredEncoder |
|||
} |
|||
return logChannel{ |
|||
encoder: zapcore.NewConsoleEncoder(config), |
|||
writers: []zapcore.WriteSyncer{}, // without any writer
|
|||
} |
|||
} |
|||
|
|||
// update refreshes the binding of the log core to the writers.
|
|||
func (handle *logCore) update() { |
|||
buildCore := func(channel *logChannel) zapcore.Core { // build zap core from logChannel
|
|||
return zapcore.NewCore( |
|||
channel.encoder, |
|||
zap.CombineWriteSyncers(channel.writers...), |
|||
handle.level, |
|||
) |
|||
} |
|||
handle.entry = zap.New( |
|||
zapcore.NewTee(buildCore(&handle.plain), buildCore(&handle.colored)), |
|||
zap.AddCaller(), zap.AddCallerSkip(1), |
|||
).Named("xproxy").Sugar() |
|||
} |
|||
|
|||
// addPlainWrites adds plain text writers to the logCore.
|
|||
func (handle *logCore) addPlainWrites(writers ...zapcore.WriteSyncer) { |
|||
handle.plain.writers = append(handle.plain.writers, writers...) |
|||
handle.update() |
|||
} |
|||
|
|||
// addColoredWrites adds colored text writers to the logCore.
|
|||
func (handle *logCore) addColoredWrites(writers ...zapcore.WriteSyncer) { |
|||
handle.colored.writers = append(handle.colored.writers, writers...) |
|||
handle.update() |
|||
} |
@ -0,0 +1,47 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"github.com/stretchr/testify/assert" |
|||
"go.uber.org/zap/zapcore" |
|||
"os" |
|||
"path" |
|||
"testing" |
|||
) |
|||
|
|||
func Test_init(t *testing.T) { |
|||
pwd := path.Dir(zapCaller().File) |
|||
assert.Equal(t, path.Join(pwd, "../"), project) |
|||
|
|||
assert.NotNil(t, logger) |
|||
assert.NotNil(t, logger.entry) |
|||
assert.NotNil(t, logger.level) |
|||
|
|||
assert.Equal(t, logger.verbose, false) |
|||
assert.Equal(t, logger.prefix, "[XProxy]") |
|||
assert.Equal(t, logger.level.Level(), InfoLevel) |
|||
|
|||
assert.Equal(t, len(logger.plain.writers), 0) |
|||
assert.Equal(t, len(logger.colored.writers), 1) |
|||
|
|||
for _, level := range []zapcore.Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, PanicLevel} { |
|||
logger.level.SetLevel(level) |
|||
assert.Equal(t, logger.entry.Level(), level) |
|||
} |
|||
logger.level.SetLevel(InfoLevel) // revert to INFO level
|
|||
} |
|||
|
|||
func Test_addWrites(t *testing.T) { |
|||
core := new(logCore) |
|||
assert.Equal(t, len(core.plain.writers), 0) |
|||
assert.Equal(t, len(core.colored.writers), 0) |
|||
|
|||
core.entry = nil |
|||
core.addPlainWrites(os.Stdout, os.Stdout, os.Stdout) |
|||
assert.NotNil(t, core.entry) |
|||
assert.Equal(t, len(core.plain.writers), 3) |
|||
|
|||
core.entry = nil |
|||
core.addColoredWrites(os.Stderr, os.Stderr, os.Stderr) |
|||
assert.NotNil(t, core.entry) |
|||
assert.Equal(t, len(core.plain.writers), 3) |
|||
} |
@ -1,6 +1,6 @@ |
|||
package main |
|||
|
|||
import "XProxy/next/assets" |
|||
import "XProxy/assets" |
|||
|
|||
func main() { |
|||
remoteAssets := map[string]string{ |
@ -0,0 +1,114 @@ |
|||
// Code generated by mockery v2.40.1. DO NOT EDIT.
|
|||
|
|||
package mocks |
|||
|
|||
import mock "github.com/stretchr/testify/mock" |
|||
|
|||
// PrimitiveArrayEncoder is an autogenerated mock type for the PrimitiveArrayEncoder type
|
|||
type PrimitiveArrayEncoder struct { |
|||
mock.Mock |
|||
} |
|||
|
|||
// AppendBool provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendBool(_a0 bool) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendByteString provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendByteString(_a0 []byte) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendComplex128 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendComplex128(_a0 complex128) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendComplex64 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendComplex64(_a0 complex64) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendFloat32 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendFloat32(_a0 float32) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendFloat64 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendFloat64(_a0 float64) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendInt provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendInt(_a0 int) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendInt16 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendInt16(_a0 int16) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendInt32 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendInt32(_a0 int32) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendInt64 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendInt64(_a0 int64) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendInt8 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendInt8(_a0 int8) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendString provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendString(_a0 string) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendUint provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendUint(_a0 uint) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendUint16 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendUint16(_a0 uint16) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendUint32 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendUint32(_a0 uint32) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendUint64 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendUint64(_a0 uint64) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendUint8 provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendUint8(_a0 uint8) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// AppendUintptr provides a mock function with given fields: _a0
|
|||
func (_m *PrimitiveArrayEncoder) AppendUintptr(_a0 uintptr) { |
|||
_m.Called(_a0) |
|||
} |
|||
|
|||
// NewPrimitiveArrayEncoder creates a new instance of PrimitiveArrayEncoder. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
|||
// The first argument is typically a *testing.T value.
|
|||
func NewPrimitiveArrayEncoder(t interface { |
|||
mock.TestingT |
|||
Cleanup(func()) |
|||
}) *PrimitiveArrayEncoder { |
|||
mock := &PrimitiveArrayEncoder{} |
|||
mock.Mock.Test(t) |
|||
|
|||
t.Cleanup(func() { mock.AssertExpectations(t) }) |
|||
|
|||
return mock |
|||
} |
@ -1,59 +0,0 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"go.uber.org/zap/zapcore" |
|||
"io" |
|||
) |
|||
|
|||
const ( |
|||
DebugLevel = zapcore.DebugLevel |
|||
InfoLevel = zapcore.InfoLevel |
|||
WarnLevel = zapcore.WarnLevel |
|||
ErrorLevel = zapcore.ErrorLevel |
|||
PanicLevel = zapcore.PanicLevel |
|||
) |
|||
|
|||
func Debugf(template string, args ...interface{}) { |
|||
logHandle.sugar.Debugf(template, args...) |
|||
} |
|||
|
|||
func Infof(template string, args ...interface{}) { |
|||
logHandle.sugar.Infof(template, args...) |
|||
} |
|||
|
|||
func Warnf(template string, args ...interface{}) { |
|||
logHandle.sugar.Warnf(template, args...) |
|||
} |
|||
|
|||
func Errorf(template string, args ...interface{}) { |
|||
logHandle.sugar.Errorf(template, args...) |
|||
} |
|||
|
|||
func Panicf(template string, args ...interface{}) { |
|||
logHandle.sugar.Panicf(template, args...) |
|||
} |
|||
|
|||
// GetLevel return the current logger level.
|
|||
func GetLevel() zapcore.Level { |
|||
return logHandle.level.Level() |
|||
} |
|||
|
|||
// SetLevel configure logger output level. Note that debug level
|
|||
// will output more information and reduce performance.
|
|||
func SetLevel(level zapcore.Level) { |
|||
logHandle.level.SetLevel(level) |
|||
if level == DebugLevel { |
|||
logHandle.verbose = true |
|||
} else { |
|||
logHandle.verbose = false |
|||
} |
|||
} |
|||
|
|||
// AddOutputs adds more plain output channel to the logger module.
|
|||
func AddOutputs(outputs ...io.Writer) { |
|||
var writers []zapcore.WriteSyncer |
|||
for _, output := range outputs { |
|||
writers = append(writers, zapcore.AddSync(output)) |
|||
} |
|||
addWrites(writers...) |
|||
} |
@ -1,78 +0,0 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"go.uber.org/zap" |
|||
"go.uber.org/zap/zapcore" |
|||
"os" |
|||
"path" |
|||
"runtime" |
|||
) |
|||
|
|||
type logger struct { |
|||
logger *zap.Logger |
|||
level *zap.AtomicLevel |
|||
sugar *zap.SugaredLogger |
|||
writers []zapcore.WriteSyncer |
|||
stderr zapcore.Core // fixed stderr output
|
|||
prefix string // custom output prefix
|
|||
path string // project absolute path
|
|||
verbose bool // show goroutine id and caller line
|
|||
} |
|||
|
|||
var logHandle *logger // singleton logger handle
|
|||
|
|||
// logConfig generates log config for XProxy.
|
|||
func logConfig(colored bool) zapcore.EncoderConfig { |
|||
config := zapcore.EncoderConfig{ |
|||
ConsoleSeparator: " ", |
|||
MessageKey: "msg", |
|||
LevelKey: "level", |
|||
TimeKey: "time", |
|||
CallerKey: "caller", |
|||
EncodeTime: timeEncoder, |
|||
EncodeLevel: levelEncoder, |
|||
EncodeCaller: callerEncoder, |
|||
} |
|||
if colored { |
|||
config.EncodeTime = timeColoredEncoder |
|||
config.EncodeLevel = levelColoredEncoder |
|||
config.EncodeCaller = callerColoredEncoder |
|||
} |
|||
return config |
|||
} |
|||
|
|||
func init() { |
|||
zapLevel := zap.NewAtomicLevelAt(InfoLevel) // using info level in default
|
|||
zapCore := zapcore.NewCore( |
|||
zapcore.NewConsoleEncoder(logConfig(true)), // colorful output
|
|||
zapcore.Lock(os.Stderr), |
|||
zapLevel, |
|||
) |
|||
zapLogger := zap.New(zapCore, zap.AddCaller(), zap.AddCallerSkip(1)) |
|||
_, src, _, _ := runtime.Caller(0) // absolute path of current code
|
|||
logHandle = &logger{ |
|||
logger: zapLogger, |
|||
level: &zapLevel, |
|||
stderr: zapCore, |
|||
sugar: zapLogger.Sugar(), |
|||
writers: []zapcore.WriteSyncer{}, |
|||
path: path.Join(path.Dir(src), "../"), |
|||
prefix: "[XProxy]", |
|||
verbose: false, |
|||
} |
|||
} |
|||
|
|||
// addWrites adds more plain log writers.
|
|||
func addWrites(writers ...zapcore.WriteSyncer) { |
|||
logHandle.writers = append(logHandle.writers, writers...) |
|||
plainCore := zapcore.NewCore( |
|||
zapcore.NewConsoleEncoder(logConfig(false)), // without colored
|
|||
zap.CombineWriteSyncers(logHandle.writers...), |
|||
logHandle.level, |
|||
) |
|||
logHandle.logger = zap.New( |
|||
zapcore.NewTee(logHandle.stderr, plainCore), |
|||
zap.AddCaller(), zap.AddCallerSkip(1), |
|||
) |
|||
logHandle.sugar = logHandle.logger.Sugar() |
|||
} |
Loading…
Reference in new issue