mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add gjson.GetJsonMap; refract glog to improve performance;
This commit is contained in:
@ -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{} {
|
||||
|
||||
@ -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")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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日志功能
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
21
geg/os/glog/glog_stdout.go
Normal file
21
geg/os/glog/glog_stdout.go
Normal 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()
|
||||
}
|
||||
@ -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])
|
||||
|
||||
Reference in New Issue
Block a user