github.com/searKing/golang/go@v1.2.74/runtime/extern.go (about)

     1  package runtime
     2  
     3  import (
     4  	"path"
     5  	"runtime"
     6  	"strings"
     7  )
     8  
     9  // GetCallerFrame returns the caller frame of the function that calls it.
    10  // The argument skip is the number of stack frames
    11  // to skip before recording in pc, with 0 identifying the frame for Callers itself and
    12  // 1 identifying the caller of Callers.
    13  func GetCallerFrame(skip int) *runtime.Frame {
    14  	pc := make([]uintptr, 1)
    15  	n := runtime.Callers(skip+1, pc[:])
    16  	if n < 1 {
    17  		return nil
    18  	}
    19  	frame, _ := runtime.CallersFrames(pc).Next()
    20  	return &frame
    21  }
    22  
    23  // GetCaller returns the caller of the function that calls it.
    24  // The argument skip is the number of stack frames
    25  // to skip before recording in pc, with 0 identifying the frame for Callers itself and
    26  // 1 identifying the caller of Callers.
    27  func GetCaller(skip int) string {
    28  	var pc [1]uintptr
    29  	runtime.Callers(skip+1, pc[:])
    30  	f := runtime.FuncForPC(pc[0])
    31  	if f == nil {
    32  		return "Unable to find caller"
    33  	}
    34  	return f.Name()
    35  }
    36  
    37  // GetShortCaller returns the short form of GetCaller.
    38  // The argument skip is the number of stack frames
    39  // to skip before recording in pc, with 0 identifying the frame for Callers itself and
    40  // 1 identifying the caller of Callers.
    41  func GetShortCaller(skip int) string {
    42  	return strings.TrimPrefix(path.Ext(GetCaller(skip+1)), ".")
    43  }
    44  
    45  // GetCallerFuncFileLine returns the __FUNCTION__, __FILE__ and __LINE__ of the function that calls it.
    46  // The argument skip is the number of stack frames
    47  // to skip before recording in pc, with 0 identifying the frame for Callers itself and
    48  // 1 identifying the caller of Callers.
    49  func GetCallerFuncFileLine(skip int) (caller string, file string, line int) {
    50  	var ok bool
    51  	_, file, line, ok = runtime.Caller(skip + 1)
    52  	if !ok {
    53  		file = "???"
    54  		line = 0
    55  	}
    56  	return GetCaller(skip + 1), file, line
    57  }
    58  
    59  // GetShortCallerFuncFileLine returns the short form of GetCallerFuncFileLine.
    60  // The argument skip is the number of stack frames
    61  // to skip before recording in pc, with 0 identifying the frame for Callers itself and
    62  // 1 identifying the caller of Callers.
    63  func GetShortCallerFuncFileLine(skip int) (caller string, file string, line int) {
    64  	caller, file, line = GetCallerFuncFileLine(skip + 1)
    65  	return strings.TrimPrefix(path.Ext(caller), "."), path.Base(file), line
    66  }
    67  
    68  // GetCallStack Same as stdlib http server code. Manually allocate stack trace buffer size
    69  // to prevent excessively large logs
    70  func GetCallStack(size int) string {
    71  	buf := make([]byte, size)
    72  	stk := string(buf[:runtime.Stack(buf[:], false)])
    73  	lines := strings.Split(stk, "\n")
    74  	if len(lines) < 3 {
    75  		return stk
    76  	}
    77  
    78  	// trim GetCallStack
    79  	var stackLines []string
    80  	stackLines = append(stackLines, lines[0])
    81  	stackLines = append(stackLines, lines[3:]...)
    82  
    83  	return strings.Join(stackLines, "\n")
    84  }