callers.go 1022 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. package log
  2. import (
  3. "runtime"
  4. "strings"
  5. "sync"
  6. )
  7. func getSingleCallerPc(skip int) uintptr {
  8. var pc [1]uintptr
  9. runtime.Callers(skip+2, pc[:])
  10. return pc[0]
  11. }
  12. type Loc struct {
  13. Package string
  14. Function string
  15. File string
  16. Line int
  17. }
  18. // This is the package returned for a caller frame that is in the main package for a binary.
  19. const mainPackageFrameImport = "main"
  20. func locFromPc(pc uintptr) Loc {
  21. f, _ := runtime.CallersFrames([]uintptr{pc}).Next()
  22. lastSlash := strings.LastIndexByte(f.Function, '/')
  23. firstDot := strings.IndexByte(f.Function[lastSlash+1:], '.')
  24. pkg := f.Function[:lastSlash+1+firstDot]
  25. if pkg == mainPackageFrameImport {
  26. pkg = mainPackagePath()
  27. }
  28. return Loc{
  29. Package: pkg,
  30. Function: f.Function,
  31. File: f.File,
  32. Line: f.Line,
  33. }
  34. }
  35. var pcToLoc sync.Map
  36. func getMsgLogLoc(msg Msg) Loc {
  37. var pc [1]uintptr
  38. msg.Callers(1, pc[:])
  39. locIf, ok := pcToLoc.Load(pc[0])
  40. if ok {
  41. return locIf.(Loc)
  42. }
  43. loc := locFromPc(pc[0])
  44. pcToLoc.Store(pc[0], loc)
  45. return loc
  46. }