add gjson.GetJsonMap; refract glog to improve performance;

This commit is contained in:
John
2019-05-21 21:52:17 +08:00
parent e9f7b8bc0c
commit 68fa235412
10 changed files with 291 additions and 139 deletions

View File

@ -64,29 +64,44 @@ func (j *Json) GetMap(pattern string, def...interface{}) map[string]interface{}
}
// GetJson gets the value by specified <pattern>,
// and converts it to a Json object.
// and converts it to a un-concurrent-safe Json object.
func (j *Json) GetJson(pattern string, def...interface{}) *Json {
result := j.Get(pattern, def...)
if result != nil {
return New(result)
return New(result, true)
}
return nil
}
// GetJsons gets the value by specified <pattern>,
// and converts it to a slice of Json object.
// and converts it to a slice of un-concurrent-safe Json object.
func (j *Json) GetJsons(pattern string, def...interface{}) []*Json {
array := j.GetArray(pattern, def...)
if len(array) > 0 {
jsons := make([]*Json, len(array))
jsonSlice := make([]*Json, len(array))
for i := 0; i < len(array); i++ {
jsons[i] = New(array[i], !j.mu.IsSafe())
jsonSlice[i] = New(array[i], true)
}
return jsons
return jsonSlice
}
return nil
}
// GetJsonMap gets the value by specified <pattern>,
// and converts it to a map of un-concurrent-safe Json object.
func (j *Json) GetJsonMap(pattern string, def...interface{}) map[string]*Json {
m := j.GetMap(pattern, def...)
if len(m) > 0 {
jsonMap := make(map[string]*Json, len(m))
for k, v := range m {
jsonMap[k] = New(v, true)
}
return jsonMap
}
return nil
}
// GetArray gets the value by specified <pattern>,
// and converts it to a slice of []interface{}.
func (j *Json) GetArray(pattern string, def...interface{}) []interface{} {

View File

@ -264,3 +264,39 @@ func TestJson_ToJson(t *testing.T) {
})
}
func TestJson_Default(t *testing.T) {
gtest.Case(t, func() {
j := gjson.New(nil)
gtest.AssertEQ(j.Get("no", 100), 100)
gtest.AssertEQ(j.GetString("no", 100), "100")
gtest.AssertEQ(j.GetBool("no", "on"), true)
gtest.AssertEQ(j.GetInt("no", 100), 100)
gtest.AssertEQ(j.GetInt8("no", 100), int8(100))
gtest.AssertEQ(j.GetInt16("no", 100), int16(100))
gtest.AssertEQ(j.GetInt32("no", 100), int32(100))
gtest.AssertEQ(j.GetInt64("no", 100), int64(100))
gtest.AssertEQ(j.GetUint("no", 100), uint(100))
gtest.AssertEQ(j.GetUint8("no", 100), uint8(100))
gtest.AssertEQ(j.GetUint16("no", 100), uint16(100))
gtest.AssertEQ(j.GetUint32("no", 100), uint32(100))
gtest.AssertEQ(j.GetUint64("no", 100), uint64(100))
gtest.AssertEQ(j.GetFloat32("no", 123.456), float32(123.456))
gtest.AssertEQ(j.GetFloat64("no", 123.456), float64(123.456))
gtest.AssertEQ(j.GetArray("no", g.Slice{1,2,3}), g.Slice{1,2,3})
gtest.AssertEQ(j.GetInts("no", g.Slice{1,2,3}), g.SliceInt{1,2,3})
gtest.AssertEQ(j.GetFloats("no", g.Slice{1,2,3}), []float64{1,2,3})
gtest.AssertEQ(j.GetMap("no", g.Map{"k":"v"}), g.Map{"k":"v"})
gtest.AssertEQ(j.GetVar("no", 123.456).Float64(), float64(123.456))
gtest.AssertEQ(j.GetJson("no", g.Map{"k":"v"}).Get("k"), "v")
gtest.AssertEQ(j.GetJsons("no", g.Slice{
g.Map{"k1":"v1"},
g.Map{"k2":"v2"},
g.Map{"k3":"v3"},
})[0].Get("k1"), "v1")
gtest.AssertEQ(j.GetJsonMap("no", g.Map{
"m1" : g.Map{"k1":"v1"},
"m2" : g.Map{"k2":"v2"},
})["m2"].Get("k2"), "v2")
})
}

View File

@ -76,7 +76,7 @@ type ServerConfig struct {
// 日志配置
LogPath string // 存放日志的目录路径(默认为空,表示不写文件)
LogHandler LogHandler // 自定义日志处理回调方法(默认为空)
LogStdPrint bool // 是否打印日志到终端(默认开启)
LogStdout bool // 是否打印日志到终端(默认开启)
ErrorLogEnabled bool // 是否开启error log(默认开启)
AccessLogEnabled bool // 是否开启access log(默认关闭)
@ -111,7 +111,7 @@ var defaultServerConfig = ServerConfig {
SessionMaxAge : gDEFAULT_SESSION_MAX_AGE,
SessionIdName : gDEFAULT_SESSION_ID_NAME,
LogStdPrint : true,
LogStdout : true,
ErrorLogEnabled : true,
AccessLogEnabled : false,
GzipContentTypes : defaultGzipContentTypes,

View File

@ -28,12 +28,12 @@ func (s *Server)SetLogPath(path string) {
// 设置日志内容是否输出到终端,默认情况下只有错误日志才会自动输出到终端。
// 如果需要输出请求日志到终端默认情况下使用SetAccessLogEnabled方法开启请求日志特性即可。
func (s *Server)SetLogStdPrint(enabled bool) {
func (s *Server)SetLogStdout(enabled bool) {
if s.Status() == SERVER_STATUS_RUNNING {
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
return
}
s.config.LogStdPrint = enabled
s.config.LogStdout = enabled
}
// 设置是否开启access log日志功能

View File

@ -32,7 +32,7 @@ func (s *Server) handleAccessLog(r *Request) {
)
content += fmt.Sprintf(` %.3f`, float64(r.LeaveTime - r.EnterTime)/1000)
content += fmt.Sprintf(`, %s, "%s", "%s"`, r.GetClientIp(), r.Referer(), r.UserAgent())
s.logger.Cat("access").Backtrace(false, 2).StdPrint(s.config.LogStdPrint).Println(content)
s.logger.Cat("access").Backtrace(false, 2).Stdout(s.config.LogStdout).Println(content)
}
// 处理服务错误信息主要是panichttp请求的status由access log进行管理
@ -60,5 +60,5 @@ func (s *Server) handleErrorLog(error interface{}, r *Request) {
content += fmt.Sprintf(` %.3f`, float64(gtime.Microsecond() - r.EnterTime)/1000)
}
content += fmt.Sprintf(`, %s, "%s", "%s"`, r.GetClientIp(), r.Referer(), r.UserAgent())
s.logger.Cat("error").Backtrace(true, 2).StdPrint(s.config.LogStdPrint).Error(content)
s.logger.Cat("error").Backtrace(true, 2).Stdout(s.config.LogStdout).Error(content)
}

View File

@ -83,8 +83,19 @@ func SetDebug(debug bool) {
}
// SetStdPrint sets whether ouptput the logging contents to stdout, which is false in default.
func SetStdPrint(open bool) {
logger.SetStdPrint(open)
func SetStdoutPrint(enabled bool) {
logger.SetStdoutPrint(enabled)
}
// SetHeaderPrint sets whether output header of the logging contents, which is true in default.
func SetHeaderPrint(enabled bool) {
logger.SetHeaderPrint(enabled)
}
// SetPrefix sets prefix string for every logging content.
// Prefix is part of header, which means if header output is shut, no prefix will be output.
func SetPrefix(prefix string) {
logger.SetPrefix(prefix)
}
// GetPath returns the logging directory path for file logging.
@ -148,8 +159,8 @@ func Backtrace(enabled bool, skip...int) *Logger {
// StdPrint is a chaining function,
// which enables/disables stdout for the current logging content output.
func StdPrint(enabled bool) *Logger {
return logger.StdPrint(enabled)
func Stdout(enabled bool) *Logger {
return logger.Stdout(enabled)
}
// Header is a chaining function,

View File

@ -9,9 +9,9 @@
package glog
import (
"bytes"
"errors"
"fmt"
"github.com/gogf/gf/g/container/gtype"
"github.com/gogf/gf/g/os/gfile"
"github.com/gogf/gf/g/os/gfpool"
"github.com/gogf/gf/g/os/gtime"
@ -20,21 +20,21 @@ import (
"os"
"runtime"
"strings"
"sync"
"time"
)
type Logger struct {
mu sync.RWMutex
pr *Logger // Parent logger.
writer io.Writer // Customized io.Writer.
path *gtype.String // Logging directory path.
file *gtype.String // Format for logging file.
level *gtype.Int // Output level.
btSkip *gtype.Int // Skip count for backtrace.
btStatus *gtype.Int // Backtrace status(1: enabled - default; 0: disabled)
printHeader *gtype.Bool // Print header or not(true in default).
alsoStdPrint *gtype.Bool // Output to stdout or not(true in default).
parent *Logger // Parent logger.
writer io.Writer // Customized io.Writer.
flags int // Extra flags for logging output features.
path string // Logging directory path.
file string // Format for logging file.
level int // Output level.
prefix string // Prefix string for every logging content.
btSkip int // Skip count for backtrace.
btStatus int // Backtrace status(1: enabled - default; 0: disabled)
headerPrint bool // Print header or not(true in default).
stdoutPrint bool // Output to stdout or not(true in default).
}
const (
@ -44,11 +44,20 @@ const (
gDEFAULT_FPOOL_EXPIRE = 60000
)
const (
F_NO_HEADER = 1 << iota // No header print.
F_NO_STDOUT // No stdout print.
F_FILE_LONG // Print full file name and line number: /a/b/c/d.go:23.
F_FILE_SHORT // Print final file name element and line number: d.go:23. overrides F_FILE_LONG.
F_TIME_DATE // Print the date in the local time zone: 2009-01-23.
F_TIME_TIME // Print the time in the local time zone: 01:23:23.
F_TIME_MILLI // Print the time with milliseconds in the local time zone: 01:23:23.675.
F_TIME_STD = F_TIME_DATE | F_TIME_MILLI
)
var (
// Default line break.
ln = "\n"
// Mutex to ensure log output sequence.
stdMu = sync.RWMutex{}
ln = "\n"
)
func init() {
@ -61,14 +70,13 @@ func init() {
// New creates and returns a custom logger.
func New() *Logger {
logger := &Logger {
path : gtype.NewString(),
file : gtype.NewString(gDEFAULT_FILE_FORMAT),
level : gtype.NewInt(defaultLevel.Val()),
btSkip : gtype.NewInt(),
btStatus : gtype.NewInt(1),
printHeader : gtype.NewBool(true),
alsoStdPrint : gtype.NewBool(true),
file : gDEFAULT_FILE_FORMAT,
level : defaultLevel.Val(),
btStatus : 1,
headerPrint : true,
stdoutPrint : true,
}
// Default writer
logger.writer = &Writer {
logger : logger,
}
@ -78,15 +86,18 @@ func New() *Logger {
// Clone returns a new logger, which is the clone the current logger.
func (l *Logger) Clone() *Logger {
logger := &Logger {
pr : l,
path : l.path.Clone(),
file : l.file.Clone(),
level : l.level.Clone(),
btSkip : l.btSkip.Clone(),
btStatus : l.btStatus.Clone(),
printHeader : l.printHeader.Clone(),
alsoStdPrint : l.alsoStdPrint.Clone(),
parent : l,
path : l.path,
file : l.file,
level : l.level,
flags : l.flags,
prefix : l.prefix,
btSkip : l.btSkip,
btStatus : l.btStatus,
headerPrint : l.headerPrint,
stdoutPrint : l.stdoutPrint,
}
// Default writer
logger.writer = &Writer {
logger : logger,
}
@ -95,36 +106,46 @@ func (l *Logger) Clone() *Logger {
// SetLevel sets the logging level.
func (l *Logger) SetLevel(level int) {
l.level.Set(level)
l.level = level
}
// GetLevel returns the logging level value.
func (l *Logger) GetLevel() int {
return l.level.Val()
return l.level
}
// SetDebug enables/disables the debug level for logger.
// The debug level is enabled in default.
func (l *Logger) SetDebug(debug bool) {
if debug {
l.level.Set(l.level.Val() | LEVEL_DEBU)
l.level = l.level | LEVEL_DEBU
} else {
l.level.Set(l.level.Val() & ^LEVEL_DEBU)
l.level = l.level & ^LEVEL_DEBU
}
}
// SetFlags sets extra flags for logging output features
func (l *Logger) SetFlags(flags int) {
l.flags = flags
}
// GetFlags returns the flags of logger.
func (l *Logger) GetFlags() int {
return l.flags
}
// SetBacktrace enables/disables the backtrace feature in failure logging outputs.
func (l *Logger) SetBacktrace(enabled bool) {
if enabled {
l.btStatus.Set(1)
l.btStatus = 1
} else {
l.btStatus.Set(0)
l.btStatus = 0
}
}
// SetBacktraceSkip sets the backtrace offset from the end point.
func (l *Logger) SetBacktraceSkip(skip int) {
l.btSkip.Set(skip)
l.btSkip = skip
}
// SetWriter sets the customized logging <writer> for logging.
@ -132,26 +153,21 @@ func (l *Logger) SetBacktraceSkip(skip int) {
// Developer can use customized logging <writer> to redirect logging output to another service,
// eg: kafka, mysql, mongodb, etc.
func (l *Logger) SetWriter(writer io.Writer) {
l.mu.Lock()
l.writer = writer
l.mu.Unlock()
}
// GetWriter returns the customized writer object, which implements the io.Writer interface.
// It returns a default writer if no customized writer set.
func (l *Logger) GetWriter() io.Writer {
l.mu.RLock()
r := l.writer
l.mu.RUnlock()
return r
return l.writer
}
// getFilePointer returns the file pinter for file logging.
// It returns nil if file logging is disabled, or file opening fails.
func (l *Logger) getFilePointer() *gfpool.File {
if path := l.path.Val(); path != "" {
if path := l.path; path != "" {
// Content containing "{}" in the file name is formatted using gtime
file, _ := gregex.ReplaceStringFunc(`{.+?}`, l.file.Val(), func(s string) string {
file, _ := gregex.ReplaceStringFunc(`{.+?}`, l.file, func(s string) string {
return gtime.Now().Format(strings.Trim(s, "{}"))
})
// Create path if it does not exist。
@ -182,33 +198,44 @@ func (l *Logger) SetPath(path string) error {
return err
}
}
l.path.Set(strings.TrimRight(path, gfile.Separator))
l.path = strings.TrimRight(path, gfile.Separator)
return nil
}
// GetPath returns the logging directory path for file logging.
// It returns empty string if no directory path set.
func (l *Logger) GetPath() string {
return l.path.Val()
return l.path
}
// SetFile sets the file name <pattern> for file logging.
// Datetime pattern can be used in <pattern>, eg: access-{Ymd}.log.
// The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log
func (l *Logger) SetFile(pattern string) {
l.file.Set(pattern)
l.file = pattern
}
// SetStdPrint sets whether output the logging contents to stdout, which is false in default.
func (l *Logger) SetStdPrint(enabled bool) {
l.alsoStdPrint.Set(enabled)
// SetStdPrint sets whether output the logging contents to stdout, which is true in default.
func (l *Logger) SetStdoutPrint(enabled bool) {
l.stdoutPrint = enabled
}
// SetHeaderPrint sets whether output header of the logging contents, which is true in default.
func (l *Logger) SetHeaderPrint(enabled bool) {
l.headerPrint = enabled
}
// SetPrefix sets prefix string for every logging content.
// Prefix is part of header, which means if header output is shut, no prefix will be output.
func (l *Logger) SetPrefix(prefix string) {
l.prefix = prefix
}
// print prints <s> to defined writer, logging file or passed <std>.
// It internally uses memory lock for file logging to ensure logging sequence.
func (l *Logger) print(std io.Writer, s string) {
// Customized writer has the most high priority.
if l.printHeader.Val() {
if l.headerPrint {
s = l.format(s)
}
writer := l.GetWriter()
@ -220,31 +247,26 @@ func (l *Logger) print(std io.Writer, s string) {
}
}
// Also output to stdout?
if l.alsoStdPrint.Val() {
l.doStdLockPrint(std, s)
if l.stdoutPrint {
if _, err := std.Write([]byte(s)); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
}
} else {
l.doStdLockPrint(writer, s)
if _, err := std.Write([]byte(s)); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
}
}
// doStdLockPrint prints <s> to <std> concurrent-safely.
func (l *Logger) doStdLockPrint(std io.Writer, s string) {
stdMu.Lock()
if _, err := std.Write([]byte(s)); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
stdMu.Unlock()
}
// stdPrint prints content <s> without backtrace.
func (l *Logger) stdPrint(s string) {
// printStd prints content <s> without backtrace.
func (l *Logger) printStd(s string) {
l.print(os.Stdout, s)
}
// stdPrint prints content <s> with backtrace check.
func (l *Logger) errPrint(s string) {
if l.btStatus.Val() == 1 {
// printStd prints content <s> with backtrace check.
func (l *Logger) printErr(s string) {
if l.btStatus == 1 {
s = l.appendBacktrace(s)
}
// In matter of sequence, do not use stderr here, but use the same stdout.
@ -296,7 +318,7 @@ func (l *Logger) GetBacktrace(skip...int) string {
}
// 从业务文件开始位置根据自定义的skip开始backtrace
goRoot := runtime.GOROOT()
for i := from + customSkip + l.btSkip.Val(); i < 10000; i++ {
for i := from + customSkip + l.btSkip; i < 10000; i++ {
if _, file, cline, ok := runtime.Caller(i); ok && file != "" {
// 不打印出go源码路径及glog包文件路径日志打印必须从业务源码文件开始且从glog包文件开始检索
if (goRoot == "" || !gregex.IsMatchString("^" + goRoot, file)) && !gregex.IsMatchString(`<autogenerated>`, file) {
@ -310,171 +332,211 @@ func (l *Logger) GetBacktrace(skip...int) string {
return backtrace
}
func (l *Logger) format(s string) string {
return time.Now().Format("2006-01-02 15:04:05.000 ") + s
func (l *Logger) format(content string) string {
buffer := bytes.NewBuffer(nil)
timeFormat := ""
if l.flags & F_TIME_DATE > 0 {
timeFormat += "2006-01-02 "
}
if l.flags & F_TIME_TIME > 0 {
timeFormat += "15:04:05 "
}
if l.flags & F_TIME_MILLI > 0 {
timeFormat += "15:04:05.000 "
}
if len(timeFormat) > 0 {
buffer.WriteString(time.Now().Format(timeFormat))
}
callerPath := ""
if l.flags & F_FILE_LONG > 0 {
callerPath = l.getLongFile() + ": "
}
if l.flags & F_FILE_SHORT > 0 {
callerPath = gfile.Basename(l.getLongFile()) + ": "
}
if len(callerPath) > 0 {
buffer.WriteString(callerPath)
}
if len(l.prefix) > 0 {
buffer.WriteString(l.prefix + " ")
}
buffer.WriteString(content)
return buffer.String()
}
// getLongFile returns the absolute file path of the caller.
func (l *Logger) getLongFile() string {
for i := 0; i < 100; i++ {
if _, file, line, ok := runtime.Caller(i); ok {
if !gregex.IsMatchString("/g/os/glog/glog.+$", file) {
return fmt.Sprintf(`%s:%d`, file, line)
}
}
}
return ""
}
func (l *Logger) Print(v ...interface{}) {
l.stdPrint(fmt.Sprintln(v...))
l.printStd(fmt.Sprintln(v...))
}
func (l *Logger) Printf(format string, v ...interface{}) {
l.stdPrint(fmt.Sprintf(format, v...))
l.printStd(fmt.Sprintf(format, v...))
}
func (l *Logger) Println(v ...interface{}) {
l.stdPrint(fmt.Sprintln(v...))
l.printStd(fmt.Sprintln(v...))
}
func (l *Logger) Printfln(format string, v ...interface{}) {
l.stdPrint(fmt.Sprintf(format + ln, v...))
l.printStd(fmt.Sprintf(format + ln, v...))
}
// Fatal prints the logging content with [FATA] header and newline, then exit the current process.
func (l *Logger) Fatal(v ...interface{}) {
l.errPrint("[FATA] " + fmt.Sprintln(v...))
l.printErr("[FATA] " + fmt.Sprintln(v...))
os.Exit(1)
}
// Fatalf prints the logging content with [FATA] header and custom format, then exit the current process.
func (l *Logger) Fatalf(format string, v ...interface{}) {
l.errPrint("[FATA] " + fmt.Sprintf(format, v...))
l.printErr("[FATA] " + fmt.Sprintf(format, v...))
os.Exit(1)
}
// Fatalf prints the logging content with [FATA] header, custom format and newline, then exit the current process.
func (l *Logger) Fatalfln(format string, v ...interface{}) {
l.errPrint("[FATA] " + fmt.Sprintf(format + ln, v...))
l.printErr("[FATA] " + fmt.Sprintf(format + ln, v...))
os.Exit(1)
}
func (l *Logger) Panic(v ...interface{}) {
s := fmt.Sprintln(v...)
l.errPrint("[PANI] " + s)
l.printErr("[PANI] " + s)
panic(s)
}
func (l *Logger) Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
l.errPrint("[PANI] " + s)
l.printErr("[PANI] " + s)
panic(s)
}
func (l *Logger) Panicfln(format string, v ...interface{}) {
s := fmt.Sprintf(format + ln, v...)
l.errPrint("[PANI] " + s)
l.printErr("[PANI] " + s)
panic(s)
}
func (l *Logger) Info(v ...interface{}) {
if l.checkLevel(LEVEL_INFO) {
l.stdPrint("[INFO] " + fmt.Sprintln(v...))
l.printStd("[INFO] " + fmt.Sprintln(v...))
}
}
func (l *Logger) Infof(format string, v ...interface{}) {
if l.checkLevel(LEVEL_INFO) {
l.stdPrint("[INFO] " + fmt.Sprintf(format, v...))
l.printStd("[INFO] " + fmt.Sprintf(format, v...))
}
}
func (l *Logger) Infofln(format string, v ...interface{}) {
if l.checkLevel(LEVEL_INFO) {
l.stdPrint("[INFO] " + fmt.Sprintf(format, v...) + ln)
l.printStd("[INFO] " + fmt.Sprintf(format, v...) + ln)
}
}
func (l *Logger) Debug(v ...interface{}) {
if l.checkLevel(LEVEL_DEBU) {
l.stdPrint("[DEBU] " + fmt.Sprintln(v...))
l.printStd("[DEBU] " + fmt.Sprintln(v...))
}
}
func (l *Logger) Debugf(format string, v ...interface{}) {
if l.checkLevel(LEVEL_DEBU) {
l.stdPrint("[DEBU] " + fmt.Sprintf(format, v...))
l.printStd("[DEBU] " + fmt.Sprintf(format, v...))
}
}
func (l *Logger) Debugfln(format string, v ...interface{}) {
if l.checkLevel(LEVEL_DEBU) {
l.stdPrint("[DEBU] " + fmt.Sprintf(format, v...) + ln)
l.printStd("[DEBU] " + fmt.Sprintf(format, v...) + ln)
}
}
func (l *Logger) Notice(v ...interface{}) {
if l.checkLevel(LEVEL_NOTI) {
l.errPrint("[NOTI] " + fmt.Sprintln(v...))
l.printErr("[NOTI] " + fmt.Sprintln(v...))
}
}
func (l *Logger) Noticef(format string, v ...interface{}) {
if l.checkLevel(LEVEL_NOTI) {
l.errPrint("[NOTI] " + fmt.Sprintf(format, v...))
l.printErr("[NOTI] " + fmt.Sprintf(format, v...))
}
}
func (l *Logger) Noticefln(format string, v ...interface{}) {
if l.checkLevel(LEVEL_NOTI) {
l.errPrint("[NOTI] " + fmt.Sprintf(format, v...) + ln)
l.printErr("[NOTI] " + fmt.Sprintf(format, v...) + ln)
}
}
func (l *Logger) Warning(v ...interface{}) {
if l.checkLevel(LEVEL_WARN) {
l.errPrint("[WARN] " + fmt.Sprintln(v...))
l.printErr("[WARN] " + fmt.Sprintln(v...))
}
}
func (l *Logger) Warningf(format string, v ...interface{}) {
if l.checkLevel(LEVEL_WARN) {
l.errPrint("[WARN] " + fmt.Sprintf(format, v...))
l.printErr("[WARN] " + fmt.Sprintf(format, v...))
}
}
func (l *Logger) Warningfln(format string, v ...interface{}) {
if l.checkLevel(LEVEL_WARN) {
l.errPrint("[WARN] " + fmt.Sprintf(format, v...) + ln)
l.printErr("[WARN] " + fmt.Sprintf(format, v...) + ln)
}
}
func (l *Logger) Error(v ...interface{}) {
if l.checkLevel(LEVEL_ERRO) {
l.errPrint("[ERRO] " + fmt.Sprintln(v...))
l.printErr("[ERRO] " + fmt.Sprintln(v...))
}
}
func (l *Logger) Errorf(format string, v ...interface{}) {
if l.checkLevel(LEVEL_ERRO) {
l.errPrint("[ERRO] " + fmt.Sprintf(format, v...))
l.printErr("[ERRO] " + fmt.Sprintf(format, v...))
}
}
func (l *Logger) Errorfln(format string, v ...interface{}) {
if l.checkLevel(LEVEL_ERRO) {
l.errPrint("[ERRO] " + fmt.Sprintf(format, v...) + ln)
l.printErr("[ERRO] " + fmt.Sprintf(format, v...) + ln)
}
}
func (l *Logger) Critical(v ...interface{}) {
if l.checkLevel(LEVEL_CRIT) {
l.errPrint("[CRIT] " + fmt.Sprintln(v...))
l.printErr("[CRIT] " + fmt.Sprintln(v...))
}
}
func (l *Logger) Criticalf(format string, v ...interface{}) {
if l.checkLevel(LEVEL_CRIT) {
l.errPrint("[CRIT] " + fmt.Sprintf(format, v...))
l.printErr("[CRIT] " + fmt.Sprintf(format, v...))
}
}
func (l *Logger) Criticalfln(format string, v ...interface{}) {
if l.checkLevel(LEVEL_CRIT) {
l.errPrint("[CRIT] " + fmt.Sprintf(format, v...) + ln)
l.printErr("[CRIT] " + fmt.Sprintf(format, v...) + ln)
}
}
// checkLevel checks whether the given <level> could be output.
func (l *Logger) checkLevel(level int) bool {
return l.level.Val() & level > 0
return l.level & level > 0
}

View File

@ -15,7 +15,7 @@ import (
// which redirects current logging content output to the specified <writer>.
func (l *Logger) To(writer io.Writer) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
@ -28,7 +28,7 @@ func (l *Logger) To(writer io.Writer) *Logger {
// which sets the directory path to <path> for current logging content output.
func (l *Logger) Path(path string) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
@ -44,14 +44,13 @@ func (l *Logger) Path(path string) *Logger {
// Param <category> can be hierarchical, eg: module/user.
func (l *Logger) Cat(category string) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
}
path := l.path.Val()
if path != "" {
logger.SetPath(path + gfile.Separator + category)
if logger.path != "" {
logger.SetPath(logger.path + gfile.Separator + category)
}
return logger
}
@ -60,7 +59,7 @@ func (l *Logger) Cat(category string) *Logger {
// which sets file name <pattern> for the current logging content output.
func (l *Logger) File(file string) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
@ -73,7 +72,7 @@ func (l *Logger) File(file string) *Logger {
// which sets logging level for the current logging content output.
func (l *Logger) Level(level int) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
@ -86,7 +85,7 @@ func (l *Logger) Level(level int) *Logger {
// which sets backtrace options for the current logging content output .
func (l *Logger) Backtrace(enabled bool, skip...int) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
@ -98,28 +97,34 @@ func (l *Logger) Backtrace(enabled bool, skip...int) *Logger {
return logger
}
// StdPrint is a chaining function,
// Stdout is a chaining function,
// which enables/disables stdout for the current logging content output.
func (l *Logger) Stdout(enabled bool) *Logger {
logger := (*Logger)(nil)
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
}
logger.stdoutPrint = enabled
return logger
}
// See Stdout.
// Deprecated.
func (l *Logger) StdPrint(enabled bool) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
logger = l.Clone()
} else {
logger = l
}
logger.SetStdPrint(enabled)
return logger
return l.Stdout(enabled)
}
// Header is a chaining function,
// which enables/disables log header for the current logging content output.
func (l *Logger) Header(enabled bool) *Logger {
logger := (*Logger)(nil)
if l.pr == nil {
if l.parent == nil {
logger = l.Clone()
} else {
logger = l
}
logger.printHeader.Set(enabled)
logger.SetHeaderPrint(enabled)
return logger
}

View File

@ -0,0 +1,21 @@
package main
import (
"github.com/gogf/gf/g/os/glog"
"sync"
)
func main() {
wg := sync.WaitGroup{}
c := make(chan struct{})
wg.Add(3000)
for i := 0; i < 3000; i++ {
go func() {
<-c
glog.Println("abcdefghijklmnopqrstuvwxyz1234567890")
wg.Done()
}()
}
close(c)
wg.Wait()
}

View File

@ -3,12 +3,14 @@ package main
import (
"fmt"
"github.com/gogf/gf/g"
"github.com/gogf/gf/g/os/gfile"
"github.com/gogf/gf/g/util/gconv"
"log"
"os"
)
func main() {
fmt.Println(gfile.Dir("/"))
var mylog = log.New(os.Stdout, "[Api] ", log.LstdFlags|log.Lshortfile)
mylog.Println(123)
return
a := []int{1,2,3}
fmt.Println(a[:0])