diff --git a/g/database/gdb/gdb_config.go b/g/database/gdb/gdb_config.go index 1ecfe42fb..4ff704812 100644 --- a/g/database/gdb/gdb_config.go +++ b/g/database/gdb/gdb_config.go @@ -9,8 +9,9 @@ package gdb import ( "fmt" - "github.com/gogf/gf/g/container/gring" "sync" + + "github.com/gogf/gf/g/container/gring" ) const ( @@ -30,7 +31,7 @@ type ConfigNode struct { User string // 账号 Pass string // 密码 Name string // 数据库名称 - Type string // 数据库类型:mysql, sqlite, mssql, pgsql, oracle(目前仅支持mysql) + Type string // 数据库类型:mysql, sqlite, mssql, pgsql, oracle Role string // (可选,默认为master)数据库的角色,用于主从操作分离,至少需要有一个master,参数值:master, slave Charset string // (可选,默认为 utf8)编码,默认为 utf8 Priority int // (可选)用于负载均衡的权重计算,当集群中只有一个节点时,权重没有任何意义 @@ -136,24 +137,24 @@ func SetDefaultGroup(name string) { // 获取默认链接的数据库链接配置项(默认是 default) func GetDefaultGroup() string { defer instances.Clear() - configs.Lock() - defer configs.Unlock() + configs.RLock() + defer configs.RUnlock() return configs.defaultGroup } // 设置数据库连接池中空闲链接的大小 -func (bs *dbBase) SetMaxIdleConns(n int) { +func (bs *dbBase) SetMaxIdleConnCount(n int) { bs.maxIdleConnCount.Set(n) } // 设置数据库连接池最大打开的链接数量 -func (bs *dbBase) SetMaxOpenConns(n int) { +func (bs *dbBase) SetMaxOpenConnCount(n int) { bs.maxOpenConnCount.Set(n) } // 设置数据库连接可重复利用的时间,超过该时间则被关闭废弃 // 如果 d <= 0 表示该链接会一直重复利用 -func (bs *dbBase) SetConnMaxLifetime(n int) { +func (bs *dbBase) SetMaxConnLifetime(n int) { bs.maxConnLifetime.Set(n) } diff --git a/g/database/gdb/gdb_func.go b/g/database/gdb/gdb_func.go index a225719d5..23ed73964 100644 --- a/g/database/gdb/gdb_func.go +++ b/g/database/gdb/gdb_func.go @@ -10,14 +10,15 @@ import ( "bytes" "errors" "fmt" + "reflect" + "strings" + "time" + "github.com/gogf/gf/g/os/glog" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/text/gstr" "github.com/gogf/gf/g/util/gconv" - "reflect" - "strings" - "time" ) // Type assert api for String(). @@ -173,7 +174,7 @@ func printSql(v *Sql) { ) if v.Error != nil { s += "\nError: " + v.Error.Error() - glog.Backtrace(true, 2).Error(s) + glog.Stack(true, 2).Error(s) } else { glog.Debug(s) } diff --git a/g/internal/debug/stack.go b/g/internal/debug/stack.go new file mode 100644 index 000000000..2bb9600c5 --- /dev/null +++ b/g/internal/debug/stack.go @@ -0,0 +1,50 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package debug contains facilities for programs to debug themselves while +// they are running. +package debug + +import ( + "bytes" + "fmt" + "runtime" + "strconv" +) + +// PrintStack prints to standard error the stack trace returned by runtime.Stack. +func PrintStack(skip ...int) { + fmt.Print(string(Stack(skip...))) +} + +// Stack returns a formatted stack trace of the goroutine that calls it. +// It calls runtime.Stack with a large enough buffer to capture the entire trace. +func Stack(skip ...int) []byte { + buffer := make([]byte, 512) + number := 0 + if len(skip) > 0 { + number = skip[0] + } + for { + n := runtime.Stack(buffer, false) + if n < len(buffer) { + lines := bytes.Split(buffer[:n], []byte{'\n'}) + index := 1 + stacks := bytes.NewBuffer(nil) + for i, line := range lines { + if i < 5+number*2 || len(line) == 0 { + continue + } + if i%2 != 0 { + stacks.WriteString(strconv.Itoa(index) + ".\t") + index++ + } + stacks.Write(line) + stacks.WriteByte('\n') + } + return stacks.Bytes() + } + buffer = make([]byte, 2*len(buffer)) + } +} diff --git a/g/net/ghttp/ghttp_server_log.go b/g/net/ghttp/ghttp_server_log.go index 745155e22..cc08b828c 100644 --- a/g/net/ghttp/ghttp_server_log.go +++ b/g/net/ghttp/ghttp_server_log.go @@ -9,6 +9,7 @@ package ghttp import ( "fmt" + "github.com/gogf/gf/g/os/gtime" ) @@ -32,7 +33,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).Stdout(s.config.LogStdout).Println(content) + s.logger.Cat("access").Stack(false, 2).Stdout(s.config.LogStdout).Println(content) } // 处理服务错误信息,主要是panic,http请求的status由access log进行管理 @@ -60,5 +61,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).Stdout(s.config.LogStdout).Error(content) + s.logger.Cat("error").Stack(true, 2).Stdout(s.config.LogStdout).Error(content) } diff --git a/g/os/glog/glog.go b/g/os/glog/glog.go index 474d7af2d..b6bee7509 100644 --- a/g/os/glog/glog.go +++ b/g/os/glog/glog.go @@ -8,9 +8,10 @@ package glog import ( + "io" + "github.com/gogf/gf/g/internal/cmdenv" "github.com/gogf/gf/g/os/grpool" - "io" ) const ( @@ -115,19 +116,19 @@ func GetFlags() int { return logger.GetFlags() } -// PrintBacktrace prints the caller backtrace, -// the optional parameter specify the skipped backtrace offset from the end point. -func PrintBacktrace(skip ...int) { - logger.PrintBacktrace(skip...) +// PrintStack prints the caller stack, +// the optional parameter specify the skipped stack offset from the end point. +func PrintStack(skip ...int) { + logger.PrintStack(skip...) } -// GetBacktrace returns the caller backtrace content, -// the optional parameter specify the skipped backtrace offset from the end point. -func GetBacktrace(skip ...int) string { - return logger.GetBacktrace(skip...) +// GetStack returns the caller stack content, +// the optional parameter specify the skipped stack offset from the end point. +func GetStack(skip ...int) string { + return logger.GetStack(skip...) } -// SetBacktrace enables/disables the backtrace feature in failure logging outputs. -func SetBacktrace(enabled bool) { - logger.SetBacktrace(enabled) +// SetStack enables/disables the stack feature in failure logging outputs. +func SetStack(enabled bool) { + logger.SetStack(enabled) } diff --git a/g/os/glog/glog_api.go b/g/os/glog/glog_api.go index 1a127a012..52c9bfb1d 100644 --- a/g/os/glog/glog_api.go +++ b/g/os/glog/glog_api.go @@ -94,13 +94,13 @@ func Debugfln(format string, v ...interface{}) { } // Notice prints the logging content with [NOTI] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Notice(v ...interface{}) { logger.Notice(v...) } // Noticef prints the logging content with [NOTI] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Noticef(format string, v ...interface{}) { logger.Noticef(format, v...) } @@ -112,13 +112,13 @@ func Noticefln(format string, v ...interface{}) { } // Warning prints the logging content with [WARN] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Warning(v ...interface{}) { logger.Warning(v...) } // Warningf prints the logging content with [WARN] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Warningf(format string, v ...interface{}) { logger.Warningf(format, v...) } @@ -130,13 +130,13 @@ func Warningfln(format string, v ...interface{}) { } // Error prints the logging content with [ERRO] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Error(v ...interface{}) { logger.Error(v...) } // Errorf prints the logging content with [ERRO] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Errorf(format string, v ...interface{}) { logger.Errorf(format, v...) } @@ -148,13 +148,13 @@ func Errorfln(format string, v ...interface{}) { } // Critical prints the logging content with [CRIT] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Critical(v ...interface{}) { logger.Critical(v...) } // Criticalf prints the logging content with [CRIT] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func Criticalf(format string, v ...interface{}) { logger.Criticalf(format, v...) } diff --git a/g/os/glog/glog_chaining.go b/g/os/glog/glog_chaining.go index f380c0e02..7195f22bf 100644 --- a/g/os/glog/glog_chaining.go +++ b/g/os/glog/glog_chaining.go @@ -46,16 +46,16 @@ func Level(level int) *Logger { } // Skip is a chaining function, -// which sets backtrace skip for the current logging content output. +// which sets stack skip for the current logging content output. // It also affects the caller file path checks when line number printing enabled. func Skip(skip int) *Logger { return logger.Skip(skip) } -// Backtrace is a chaining function, -// which sets backtrace options for the current logging content output . -func Backtrace(enabled bool, skip ...int) *Logger { - return logger.Backtrace(enabled, skip...) +// Stack is a chaining function, +// which sets stack options for the current logging content output . +func Stack(enabled bool, skip ...int) *Logger { + return logger.Stack(enabled, skip...) } // StdPrint is a chaining function, diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index 49e448352..788451af7 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -10,17 +10,19 @@ import ( "bytes" "errors" "fmt" + "io" + "os" + "runtime" + "strings" + "time" + + "github.com/gogf/gf/g/internal/debug" + "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/os/gfpool" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/util/gconv" - "io" - "os" - "regexp" - "runtime" - "strings" - "time" ) type Logger struct { @@ -31,8 +33,8 @@ type Logger struct { 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) + stSkip int // Skip count for stack. + stStatus int // Stack 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). } @@ -72,7 +74,7 @@ func New() *Logger { file: gDEFAULT_FILE_FORMAT, flags: F_TIME_STD, level: LEVEL_ALL, - btStatus: 1, + stStatus: 1, headerPrint: true, stdoutPrint: true, } @@ -126,18 +128,18 @@ func (l *Logger) GetFlags() int { return l.flags } -// SetBacktrace enables/disables the backtrace feature in failure logging outputs. -func (l *Logger) SetBacktrace(enabled bool) { +// SetStack enables/disables the stack feature in failure logging outputs. +func (l *Logger) SetStack(enabled bool) { if enabled { - l.btStatus = 1 + l.stStatus = 1 } else { - l.btStatus = 0 + l.stStatus = 0 } } -// SetBacktraceSkip sets the backtrace offset from the end point. -func (l *Logger) SetBacktraceSkip(skip int) { - l.btSkip = skip +// SetStackSkip sets the stack offset from the end point. +func (l *Logger) SetStackSkip(skip int) { + l.stSkip = skip } // SetWriter sets the customized logging for logging. @@ -305,16 +307,16 @@ func (l *Logger) printToWriter(std io.Writer, buffer *bytes.Buffer) { } } -// printStd prints content without backtrace. +// printStd prints content without stack. func (l *Logger) printStd(lead string, value ...interface{}) { l.print(os.Stdout, lead, value...) } -// printStd prints content with backtrace check. +// printStd prints content with stack check. func (l *Logger) printErr(lead string, value ...interface{}) { - if l.btStatus == 1 { - if s := l.GetBacktrace(); s != "" { - value = append(value, ln+"Backtrace:"+ln+s) + if l.stStatus == 1 { + if s := l.GetStack(); s != "" { + value = append(value, ln+"Stack:"+ln+s) } } // In matter of sequence, do not use stderr here, but use the same stdout. @@ -326,52 +328,24 @@ func (l *Logger) format(format string, value ...interface{}) string { return fmt.Sprintf(format, value...) } -// PrintBacktrace prints the caller backtrace, -// the optional parameter specify the skipped backtrace offset from the end point. -func (l *Logger) PrintBacktrace(skip ...int) { - if s := l.GetBacktrace(skip...); s != "" { - l.Println("Backtrace:" + ln + s) +// PrintStack prints the caller stack, +// the optional parameter specify the skipped stack offset from the end point. +func (l *Logger) PrintStack(skip ...int) { + if s := l.GetStack(skip...); s != "" { + l.Println("Stack:" + ln + s) } else { l.Println() } } -// GetBacktrace returns the caller backtrace content, -// the optional parameter specify the skipped backtrace offset from the end point. -func (l *Logger) GetBacktrace(skip ...int) string { - customSkip := 0 +// GetStack returns the caller stack content, +// the optional parameter specify the skipped stack offset from the end point. +func (l *Logger) GetStack(skip ...int) string { + number := 1 if len(skip) > 0 { - customSkip = skip[0] + number = skip[0] + 1 } - backtrace := "" - from := 0 - // Find the caller position exclusive of the glog file. - for i := 0; i < 1000; i++ { - if _, file, _, ok := runtime.Caller(i); ok { - if !gregex.IsMatchString("/g/os/glog/glog.+$", file) { - from = i - break - } - } - } - // Find the true caller file path using custom skip. - index := 1 - goRoot := runtime.GOROOT() - if goRoot != "" { - goRoot = strings.Replace(goRoot, "\\", "/", -1) - goRoot = regexp.QuoteMeta(goRoot) - } - for i := from + customSkip + l.btSkip; i < 1000; i++ { - if _, file, cline, ok := runtime.Caller(i); ok && len(file) > 2 { - if (goRoot == "" || !gregex.IsMatchString("^"+goRoot, file)) && !gregex.IsMatchString(``, file) { - backtrace += fmt.Sprintf(`%d. %s:%d%s`, index, file, cline, ln) - index++ - } - } else { - break - } - } - return backtrace + return string(debug.Stack(number)) } // getLongFile returns the absolute file path along with its line number of the caller. @@ -380,7 +354,7 @@ func (l *Logger) getLongFile() string { // Find the caller position exclusive of the glog file. for i := 0; i < 1000; i++ { if _, file, _, ok := runtime.Caller(i); ok { - if !gregex.IsMatchString("/g/os/glog/glog.+$", file) { + if !gregex.IsMatchString("/os/glog/glog.+$", file) { from = i break } @@ -388,7 +362,7 @@ func (l *Logger) getLongFile() string { } // Find the true caller file path using custom skip. goRoot := runtime.GOROOT() - for i := from + l.btSkip; i < 1000; i++ { + for i := from + l.stSkip; i < 1000; i++ { if _, file, line, ok := runtime.Caller(i); ok && len(file) > 2 { if (goRoot == "" || !gregex.IsMatchString("^"+goRoot, file)) && !gregex.IsMatchString(``, file) { return fmt.Sprintf(`%s:%d`, file, line) diff --git a/g/os/glog/glog_logger_api.go b/g/os/glog/glog_logger_api.go index d75fefb51..adbcdf6e2 100644 --- a/g/os/glog/glog_logger_api.go +++ b/g/os/glog/glog_logger_api.go @@ -116,7 +116,7 @@ func (l *Logger) Debugfln(format string, v ...interface{}) { } // Notice prints the logging content with [NOTI] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Notice(v ...interface{}) { if l.checkLevel(LEVEL_NOTI) { l.printErr("[NOTI]", v...) @@ -124,7 +124,7 @@ func (l *Logger) Notice(v ...interface{}) { } // Noticef prints the logging content with [NOTI] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Noticef(format string, v ...interface{}) { if l.checkLevel(LEVEL_NOTI) { l.printErr("[NOTI]", l.format(format, v...)) @@ -140,7 +140,7 @@ func (l *Logger) Noticefln(format string, v ...interface{}) { } // Warning prints the logging content with [WARN] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Warning(v ...interface{}) { if l.checkLevel(LEVEL_WARN) { l.printErr("[WARN]", v...) @@ -148,7 +148,7 @@ func (l *Logger) Warning(v ...interface{}) { } // Warningf prints the logging content with [WARN] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Warningf(format string, v ...interface{}) { if l.checkLevel(LEVEL_WARN) { l.printErr("[WARN]", l.format(format, v...)) @@ -164,7 +164,7 @@ func (l *Logger) Warningfln(format string, v ...interface{}) { } // Error prints the logging content with [ERRO] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Error(v ...interface{}) { if l.checkLevel(LEVEL_ERRO) { l.printErr("[ERRO]", v...) @@ -172,7 +172,7 @@ func (l *Logger) Error(v ...interface{}) { } // Errorf prints the logging content with [ERRO] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Errorf(format string, v ...interface{}) { if l.checkLevel(LEVEL_ERRO) { l.printErr("[ERRO]", l.format(format, v...)) @@ -188,7 +188,7 @@ func (l *Logger) Errorfln(format string, v ...interface{}) { } // Critical prints the logging content with [CRIT] header and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Critical(v ...interface{}) { if l.checkLevel(LEVEL_CRIT) { l.printErr("[CRIT]", v...) @@ -196,7 +196,7 @@ func (l *Logger) Critical(v ...interface{}) { } // Criticalf prints the logging content with [CRIT] header, custom format and newline. -// It also prints caller backtrace info if backtrace feature is enabled. +// It also prints caller stack info if stack feature is enabled. func (l *Logger) Criticalf(format string, v ...interface{}) { if l.checkLevel(LEVEL_CRIT) { l.printErr("[CRIT]", l.format(format, v...)) diff --git a/g/os/glog/glog_logger_chaining.go b/g/os/glog/glog_logger_chaining.go index d60e3366a..02e43630e 100644 --- a/g/os/glog/glog_logger_chaining.go +++ b/g/os/glog/glog_logger_chaining.go @@ -7,8 +7,9 @@ package glog import ( - "github.com/gogf/gf/g/os/gfile" "io" + + "github.com/gogf/gf/g/os/gfile" ) // To is a chaining function, @@ -82,7 +83,7 @@ func (l *Logger) Level(level int) *Logger { } // Skip is a chaining function, -// which sets backtrace skip for the current logging content output. +// which sets stack skip for the current logging content output. // It also affects the caller file path checks when line number printing enabled. func (l *Logger) Skip(skip int) *Logger { logger := (*Logger)(nil) @@ -91,22 +92,22 @@ func (l *Logger) Skip(skip int) *Logger { } else { logger = l } - logger.SetBacktraceSkip(skip) + logger.SetStackSkip(skip) return logger } -// Backtrace is a chaining function, -// which sets backtrace options for the current logging content output . -func (l *Logger) Backtrace(enabled bool, skip ...int) *Logger { +// Stack is a chaining function, +// which sets stack options for the current logging content output . +func (l *Logger) Stack(enabled bool, skip ...int) *Logger { logger := (*Logger)(nil) if l.parent == nil { logger = l.Clone() } else { logger = l } - logger.SetBacktrace(enabled) + logger.SetStack(enabled) if len(skip) > 0 { - logger.SetBacktraceSkip(skip[0]) + logger.SetStackSkip(skip[0]) } return logger } diff --git a/g/test/gtest/gtest.go b/g/test/gtest/gtest.go index 6fdeb4c11..d2c6eb40e 100644 --- a/g/test/gtest/gtest.go +++ b/g/test/gtest/gtest.go @@ -9,13 +9,14 @@ package gtest import ( "fmt" - "github.com/gogf/gf/g/util/gconv" "os" "reflect" "regexp" "runtime" "strings" "testing" + + "github.com/gogf/gf/g/util/gconv" ) // Case creates an unit test case. @@ -24,7 +25,7 @@ import ( func Case(t *testing.T, f func()) { defer func() { if err := recover(); err != nil { - fmt.Fprintf(os.Stderr, "%v\n%s", err, getBacktrace()) + fmt.Fprintf(os.Stderr, "%v\n%s", err, getStack()) t.Fail() } }() @@ -255,7 +256,7 @@ func Error(message ...interface{}) { // Fatal prints to stderr and exit the process. func Fatal(message ...interface{}) { - fmt.Fprintf(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), getBacktrace()) + fmt.Fprintf(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), getStack()) os.Exit(1) } @@ -297,14 +298,14 @@ func compareMap(value, expect interface{}) error { return nil } -// getBacktrace returns the caller backtrace content from getBacktrace. -// The parameter indicates the skip count of the caller backtrace from getBacktrace. -func getBacktrace(skip ...int) string { +// getStack returns the caller stack content from getStack. +// The parameter indicates the skip count of the caller stack from getStack. +func getStack(skip ...int) string { customSkip := 0 if len(skip) > 0 { customSkip = skip[0] } - backtrace := "" + stack := "" index := 1 from := 0 // Ignore current gtest lines and find the beginning index of caller file. @@ -335,13 +336,13 @@ func getBacktrace(skip ...int) string { continue } } - backtrace += fmt.Sprintf(`%d. %s:%d%s`, index, file, cline, "\n") + stack += fmt.Sprintf(`%d. %s:%d%s`, index, file, cline, "\n") index++ } else { break } } - return backtrace + return stack } // isNil checks whether is nil. diff --git a/g/util/gutil/gutil.go b/g/util/gutil/gutil.go index 2ef4c851e..de320ba5a 100644 --- a/g/util/gutil/gutil.go +++ b/g/util/gutil/gutil.go @@ -11,10 +11,10 @@ import ( "bytes" "encoding/json" "fmt" + "os" + "github.com/gogf/gf/g/internal/empty" "github.com/gogf/gf/g/util/gconv" - "os" - "runtime" ) // Dump prints variables to stdout with more manually readable. @@ -46,21 +46,6 @@ func Export(i ...interface{}) string { return buffer.String() } -// PrintBacktrace prints the caller backtrace to stdout. -func PrintBacktrace() { - index := 1 - buffer := bytes.NewBuffer(nil) - for i := 1; i < 10000; i++ { - if _, path, line, ok := runtime.Caller(i); ok { - buffer.WriteString(fmt.Sprintf(`%d. %s:%d%s`, index, path, line, "\n")) - index++ - } else { - break - } - } - fmt.Print(buffer.String()) -} - // Throw throws out an exception, which can be caught be TryCatch or recover. func Throw(exception interface{}) { panic(exception) diff --git a/g/util/gutil/gutil_debug.go b/g/util/gutil/gutil_debug.go new file mode 100644 index 000000000..97cf4c864 --- /dev/null +++ b/g/util/gutil/gutil_debug.go @@ -0,0 +1,36 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gutil + +import ( + "github.com/gogf/gf/g/internal/debug" +) + +// PrintStack is alias for PrintStack. +// Deprecated. +func PrintStack() { + PrintStack() +} + +// PrintStack prints to standard error the stack trace returned by runtime.Stack. +func PrintStack(skip ...int) { + number := 1 + if len(skip) > 0 { + number = skip[0] + 1 + } + debug.PrintStack(number) +} + +// Stack returns a formatted stack trace of the goroutine that calls it. +// It calls runtime.Stack with a large enough buffer to capture the entire trace. +func Stack(skip ...int) []byte { + number := 1 + if len(skip) > 0 { + number = skip[0] + 1 + } + return debug.Stack(number) +} diff --git a/g/util/gutil/gutil_comparator_z_unit_test.go b/g/util/gutil/gutil_z_comparator_z_unit_test.go similarity index 100% rename from g/util/gutil/gutil_comparator_z_unit_test.go rename to g/util/gutil/gutil_z_comparator_z_unit_test.go diff --git a/g/util/gutil/gutil_z_unit_test.go b/g/util/gutil/gutil_z_unit_test.go index cf52edc2a..05fd8a9b9 100755 --- a/g/util/gutil/gutil_z_unit_test.go +++ b/g/util/gutil/gutil_z_unit_test.go @@ -23,9 +23,9 @@ func Test_Dump(t *testing.T) { }) } -func Test_PrintBacktrace(t *testing.T) { +func Test_PrintStack(t *testing.T) { gtest.Case(t, func() { - gutil.PrintBacktrace() + gutil.PrintStack() }) } diff --git a/geg/os/glog/glog_backtrace.go b/geg/os/glog/glog_backtrace.go deleted file mode 100644 index 1cd001b7f..000000000 --- a/geg/os/glog/glog_backtrace.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "fmt" - "github.com/gogf/gf/g/os/glog" -) - -func main() { - - glog.PrintBacktrace() - glog.New().PrintBacktrace() - - fmt.Println(glog.GetBacktrace()) - fmt.Println(glog.New().GetBacktrace()) -} diff --git a/geg/os/glog/glog_stack.go b/geg/os/glog/glog_stack.go new file mode 100644 index 000000000..26e69ad26 --- /dev/null +++ b/geg/os/glog/glog_stack.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + + "github.com/gogf/gf/g/os/glog" +) + +func main() { + + glog.PrintStack() + glog.New().PrintStack() + + fmt.Println(glog.GetStack()) + fmt.Println(glog.New().GetStack()) +} diff --git a/geg/other/test.go b/geg/other/test.go index 1b134b6c5..602c93c2a 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,24 +1,13 @@ package main import ( - "github.com/gogf/gf/g" - "github.com/gogf/gf/g/net/ghttp" + "github.com/gogf/gf/g/util/gutil" ) -type Order struct{} - -func (order *Order) Get(r *ghttp.Request) { - r.Response.Write("GET") +func Test(s interface{}) { + gutil.PrintStack() } func main() { - s := g.Server() - s.BindHookHandlerByMap("/api.v1/*any", map[string]ghttp.HandlerFunc{ - "BeforeServe": func(r *ghttp.Request) { - r.Response.CORSDefault() - }, - }) - s.BindObjectRest("/api.v1/{.struct}", new(Order)) - s.SetPort(8199) - s.Run() + Test(nil) } diff --git a/geg/util/gutil/stack.go b/geg/util/gutil/stack.go new file mode 100644 index 000000000..d790d8d07 --- /dev/null +++ b/geg/util/gutil/stack.go @@ -0,0 +1,14 @@ +package main + +import ( + "github.com/gogf/gf/g/util/gutil" +) + +func Test(s *interface{}) { + //debug.PrintStack() + gutil.PrintStack() +} + +func main() { + Test(nil) +}