mirror of https://github.com/dnomd343/XProxy.git
				
				
			
				 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