diff --git a/g/encoding/gjson/gjson_api.go b/g/encoding/gjson/gjson_api.go index 028478b8e..25db8a035 100644 --- a/g/encoding/gjson/gjson_api.go +++ b/g/encoding/gjson/gjson_api.go @@ -64,29 +64,44 @@ func (j *Json) GetMap(pattern string, def...interface{}) map[string]interface{} } // GetJson gets the value by specified , -// 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 , -// 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 , +// 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 , // and converts it to a slice of []interface{}. func (j *Json) GetArray(pattern string, def...interface{}) []interface{} { diff --git a/g/encoding/gjson/gjson_z_unit_basic_test.go b/g/encoding/gjson/gjson_z_unit_basic_test.go index b1d3430f1..0a43eee58 100644 --- a/g/encoding/gjson/gjson_z_unit_basic_test.go +++ b/g/encoding/gjson/gjson_z_unit_basic_test.go @@ -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") + }) +} + diff --git a/g/net/ghttp/ghttp_server_config.go b/g/net/ghttp/ghttp_server_config.go index 5619d2e7c..6f7fbad39 100644 --- a/g/net/ghttp/ghttp_server_config.go +++ b/g/net/ghttp/ghttp_server_config.go @@ -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, diff --git a/g/net/ghttp/ghttp_server_config_logger.go b/g/net/ghttp/ghttp_server_config_logger.go index 5482de3fe..fce013d2d 100644 --- a/g/net/ghttp/ghttp_server_config_logger.go +++ b/g/net/ghttp/ghttp_server_config_logger.go @@ -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日志功能 diff --git a/g/net/ghttp/ghttp_server_log.go b/g/net/ghttp/ghttp_server_log.go index 3801abf4f..2f4b3158d 100644 --- a/g/net/ghttp/ghttp_server_log.go +++ b/g/net/ghttp/ghttp_server_log.go @@ -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) } // 处理服务错误信息,主要是panic,http请求的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) } diff --git a/g/os/glog/glog.go b/g/os/glog/glog.go index bdd08f641..adf1af58a 100644 --- a/g/os/glog/glog.go +++ b/g/os/glog/glog.go @@ -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, diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index c75333071..976be26eb 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -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 for logging. @@ -132,26 +153,21 @@ func (l *Logger) SetBacktraceSkip(skip int) { // Developer can use customized logging 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 for file logging. // Datetime pattern can be used in , 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 to defined writer, logging file or passed . // 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 to 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 without backtrace. -func (l *Logger) stdPrint(s string) { +// printStd prints content without backtrace. +func (l *Logger) printStd(s string) { l.print(os.Stdout, s) } -// stdPrint prints content with backtrace check. -func (l *Logger) errPrint(s string) { - if l.btStatus.Val() == 1 { +// printStd prints content 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(``, 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 could be output. func (l *Logger) checkLevel(level int) bool { - return l.level.Val() & level > 0 + return l.level & level > 0 } \ No newline at end of file diff --git a/g/os/glog/glog_logger_chaining.go b/g/os/glog/glog_logger_chaining.go index b478a6c76..d02eca9e2 100644 --- a/g/os/glog/glog_logger_chaining.go +++ b/g/os/glog/glog_logger_chaining.go @@ -15,7 +15,7 @@ import ( // which redirects current logging content output to the specified . 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 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 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 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 } \ No newline at end of file diff --git a/geg/os/glog/glog_stdout.go b/geg/os/glog/glog_stdout.go new file mode 100644 index 000000000..3935519ff --- /dev/null +++ b/geg/os/glog/glog_stdout.go @@ -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() +} diff --git a/geg/other/test.go b/geg/other/test.go index 47632c222..4f5b4d622 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -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])