add package internal/debug; add gutil.Stack/PrintStack; rename Backtrace to Stack for glog

This commit is contained in:
John 2019-06-29 10:45:50 +08:00
parent da907f35bd
commit d5f7ca634d
19 changed files with 229 additions and 174 deletions

View File

@ -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)
}

View File

@ -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
View 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))
}
}

View File

@ -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)
}
// 处理服务错误信息主要是panichttp请求的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)
}

View File

@ -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)
}

View File

@ -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...)
}

View File

@ -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,

View File

@ -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)

View File

@ -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...))

View File

@ -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
}

View File

@ -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.

View File

@ -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)

View 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)
}

View File

@ -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()
})
}

View File

@ -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
View 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())
}

View File

@ -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
View 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)
}