mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 03:07:45 +08:00
add package internal/debug; add gutil.Stack/PrintStack; rename Backtrace to Stack for glog
This commit is contained in:
parent
da907f35bd
commit
d5f7ca634d
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
50
g/internal/debug/stack.go
Normal file
50
g/internal/debug/stack.go
Normal file
@ -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))
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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 <skip> specify the skipped backtrace offset from the end point.
|
||||
func PrintBacktrace(skip ...int) {
|
||||
logger.PrintBacktrace(skip...)
|
||||
// PrintStack prints the caller stack,
|
||||
// the optional parameter <skip> 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 <skip> 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 <skip> 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)
|
||||
}
|
||||
|
@ -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...)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 <writer> for logging.
|
||||
@ -305,16 +307,16 @@ func (l *Logger) printToWriter(std io.Writer, buffer *bytes.Buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
// printStd prints content <s> without backtrace.
|
||||
// printStd prints content <s> without stack.
|
||||
func (l *Logger) printStd(lead string, value ...interface{}) {
|
||||
l.print(os.Stdout, lead, value...)
|
||||
}
|
||||
|
||||
// printStd prints content <s> with backtrace check.
|
||||
// printStd prints content <s> 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 <skip> 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 <skip> 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 <skip> 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 <skip> 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(`<autogenerated>`, 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(`<autogenerated>`, file) {
|
||||
return fmt.Sprintf(`%s:%d`, file, line)
|
||||
|
@ -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...))
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 <message> 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 <skip> 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 <skip> 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 <value> is nil.
|
||||
|
@ -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 <i...> 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)
|
||||
|
36
g/util/gutil/gutil_debug.go
Normal file
36
g/util/gutil/gutil_debug.go
Normal file
@ -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)
|
||||
}
|
@ -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()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
}
|
16
geg/os/glog/glog_stack.go
Normal file
16
geg/os/glog/glog_stack.go
Normal file
@ -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())
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
14
geg/util/gutil/stack.go
Normal file
14
geg/util/gutil/stack.go
Normal file
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user