Documentation ¶
Overview ¶
Package pruntime provides an interface to the Go standard library’s runtime package using only serializable simple types
Stack traces and code locations have several formats:
codeLocation := pruntime.NewCodeLocation(0) codeLocation.Base() // package and type → mypackage.(*MyType).MyFunc codeLocation.PackFunc() // very brief → mypackage.MyFunc codeLocation.Name(): // function name only → MyFunc codeLocation.Short() // line, no package path → mypackage.(*MyType).MyFunc-myfile.go:19 codeLocation.Long() // uniquely identifiable → codeberg.org/haraldrudell/mypackage.(*MyType).MyFunc-myfile.go:19 codeLocation.Full() // everything → codeberg.org/haraldrudell/mypackage.(*MyType).MyFunc-/fs/mypackage/myfile.go:19 codeLocation.String() // two lines → "codeberg.org/haraldrudell/mypackage.(*MyType).MyFunc\n /fs/mypackage/myfile.go:19"
Stack can determine where a goroutine was created and whether this is the main thread
pruntime.GoRoutineID() → 1 pruntime.NewStack(0).Creator.Short() → main.main-pruntime.go:30 fmt.Println(pruntime.NewStack(0).IsMainThread) → true pruntime.NewStack(0).Frames[0].Args → (0x104c12c60?)
Index ¶
- func AppendLocation(s string, location *CodeLocation) string
- func CpuTicks() uint32
- func DebugStack(skipFrames int) (stack string)
- func FirstStackLine() (firstStackLine []byte)
- func Invocation(stackFramesToSkip int) (stackTrace string)
- func IsCloseOfClosedChannel(err error) (is bool)
- func IsRuntimeError(err error) (err1 runtime.Error)
- func IsSendOnClosedChannel(err error) (is bool)
- func ParseFirstLine(debugStack []byte) (ID uint64, status string, err error)
- func SplitAbsoluteFunctionName(absPath string) (packagePath, packageName, typePath, funcName string)
- func StackTrace() (stackTrace []byte)
- type CacheMechanic
- type CachedLocation
- type CodeLocation
- func (cl *CodeLocation) Base() (baseName string)
- func (cl *CodeLocation) Dump() (s string)
- func (cl *CodeLocation) Full() (funcName string)
- func (cl *CodeLocation) FuncIdentifier() (funcIdentifier string)
- func (cl *CodeLocation) FuncLine() (funcLine string)
- func (cl *CodeLocation) IsSet() (isSet bool)
- func (cl *CodeLocation) Long() (funcName string)
- func (cl *CodeLocation) Name() (funcName string)
- func (cl *CodeLocation) PackFunc() (packageDotFunction string)
- func (cl *CodeLocation) Package() (packageName string)
- func (cl *CodeLocation) Short() (funcName string)
- func (cl CodeLocation) String() string
- type StackSlice
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AppendLocation ¶ added in v0.4.114
func AppendLocation(s string, location *CodeLocation) string
func CpuTicks ¶ added in v0.4.125
func CpuTicks() uint32
CpuTick is a 32-bit pseudo-random number increasing every ns
- consider prand functions based on 2 ns 32-bit thread-local runtime.fastrand
- invocation time 16 ns, similar to an uncontended sync.Mutex.Lock
- wraps around every 4 s
- getting a random number is 4 ns
- — Intn on single-threaded math/rand.New(rand.NewSource(time.Now().UnixNano()))
On Linux x86_64, this is aesrand seeded by /dev/urandom
- thread-safe because shared state is per-goroutine
- https://go.googlesource.com/go/+/refs/heads/master/src/runtime/stubs.go#124
func DebugStack ¶ added in v0.4.12
DebugStack returns a string stack trace intended to be printed or when a full printable trace is desired
- top returned stack frame is caller of pruntime.DebugStack
- skipFrames allows for removing additional frames.
- differences from debug.Stack:
- tabs are replaced with two spaces
- Stack frames other than the callers of pruntime.DebugStack are removed
func FirstStackLine ¶ added in v0.4.99
func FirstStackLine() (firstStackLine []byte)
FirstStackLine efficiently obtains the first line of a runtime.Stack
- "goroutine 34 [running]:\n…"
- interning the first line as a string will cost about 25 bytes
func Invocation ¶
Invocation returns an invocation stack trace for debug printing, empty string on troubles. The result is similar to the output from debug.Stack, but has some stack frames removed. tabs are replaced by two spaces. stackFramesToSkip 0 means first frame will be the caller of Invocation "goroutine 1 [running]:\ngithub.com/haraldrudell/parl/mains.(*Executable).AddErr(0x1809300, 0x158b620, 0xc000183800, 0x1) mains.(*Executable).AddErr-executable.go:302…"
func IsCloseOfClosedChannel ¶ added in v0.4.103
IsCloseOfClosedChannel returns true if err’s error chain contains the runtime error “close of closed channel”
func IsRuntimeError ¶
IsRuntimeError determines if err’s error chain contains a runtime.Error
- err1 is then a non-nil error value
- runtime.Error is an interface describing the unexported runtime.plainError type
func IsSendOnClosedChannel ¶
IsSendOnClosedChannel returns true if err’s error chain contains the runtime error “send on closed channel”
- runtime.plainError is an unexported named type of underlying type string
- each error occurrence has a unique runtime.plainError value
- runtime.plainError type have empty method RuntimeError()
- the runtime.Error interface has the RuntimeError method
- the Error method of runtime.Error returns the string value
func ParseFirstLine ¶ added in v0.4.129
getID obtains gorutine ID, as of go1.18 a numeric string "1"…
func SplitAbsoluteFunctionName ¶ added in v0.4.29
func SplitAbsoluteFunctionName(absPath string) ( packagePath, packageName, typePath, funcName string)
SplitAbsoluteFunctionName splits an absolute function name into its parts
- input: github.com/haraldrudell/parl/error116.(*TypeName).FuncName[...]
- packagePath: "github.com/haraldrudell/parl/"
- packageName: "error116" single identifier, not empty
- typePath: "(*TypeName)" may be empty
- funcName: "FuncName[...]"
func StackTrace ¶ added in v0.4.106
func StackTrace() (stackTrace []byte)
StackTrace returns runtime.Stack after allocating sufficient buffer
- if the entire stackTrace is converted to string and split: those substrings will be interned part of the larger stackTrace string causing memory leak, ie. If only a single character is kept, the entire block is kept. This leads to megabytes of memory leaks
- StackTrace returns a byte slice for convert smaller indiviual parts to string
- the stack trace contains spaces, newlines and tab characters for formatting
- the first line is status line
- each frame is then two lines:
- — a function line with argument values
- — a filename line beginning with a tab character and a hexadecimal in-line byte offset
- the first line-pair is for the StackTrace function itself
- if the executing thread is a goroutine:
- — the final two lines is “created by,” ie. the location of the go statement and what thread started the goroutine
- — the two preceding lines is the goroutine function
- the stack trace has a terminating newline
Types ¶
type CacheMechanic ¶ added in v0.4.131
type CacheMechanic struct {
// contains filtered or unexported fields
}
CacheMechanic ensures that an init function is executed exactly once
- sync.Once using a known number of stack frames
- initialization-free
func (*CacheMechanic) EnsureInit ¶ added in v0.4.131
func (c *CacheMechanic) EnsureInit(initFunc func())
EnsureInit ensures data is loaded exactly once
- initFunc loads data
- invocations after first EnsureInit return are atomic performance
- first invocation is locked performance
- subsequent invocations prior to first EnsureInit return are held waiting
- —
- upon return, it is guaranteed that init has completed
- order of thread-returns is not guaranteed
type CachedLocation ¶ added in v0.4.87
type CachedLocation struct {
// contains filtered or unexported fields
}
CachedLocation caches the code location and performantly provides it in string formats. Thread-safe
- one top-level CachedLocation variable is required for each code location
- code line provided is the location of first getter method
- caching saves 1,003 ns, ie. 0.85 parallel mutex Lock/Unlock
- cannot use sync.Once.Do because number of frames it consumes is unknown
- initialization-free, thread-safe
usage:
var mycl pruntime.CachedLocation func f() { println(mycl.PackFunc())
func (*CachedLocation) FuncIdentifier ¶ added in v0.4.88
func (c *CachedLocation) FuncIdentifier() (funcIdentifier string)
"myFunc" Thread-safe
func (*CachedLocation) FuncName ¶ added in v0.4.87
func (c *CachedLocation) FuncName() (location string)
"github.com/haraldrudell/parl/mains.(*Executable).AddErr" Thread-safe
- FuncName is the value compared to by [parl.SetRegexp]
func (*CachedLocation) PackFunc ¶ added in v0.4.87
func (c *CachedLocation) PackFunc() (packFunc string)
"mains.AddErr" Thread-safe
- similar to [perrors.NewPF] or [perrors.ErrorfPF]
func (*CachedLocation) Short ¶ added in v0.4.87
func (c *CachedLocation) Short() (location string)
"mains.(*Executable).AddErr-executable.go:25" Thread-safe
- similar to [perrors.Short] location
type CodeLocation ¶
type CodeLocation struct { // File is the absolute path to the go source file // // /opt/foxyboy/sw/privates/parl/mains/executable.go File string // Line is the line number in the source file, eg. 35 Line int // FuncName is the fully qualified Go package path, // a possible value or pointer receiver struct name, // and the function name // // github.com/haraldrudell/parl/mains.(*Executable).AddErr FuncName string }
CodeLocation represents an executing code location, ie. a code line in source code
- CodeLocation is similar to the location in runtime.Frame, but contains only basic types string and int
func GetCodeLocation ¶
func GetCodeLocation(rFrame *runtime.Frame) (cl *CodeLocation)
GetCodeLocation converts a runtime stack frame to a code location stack frame. runtime contains opaque types while code location consists of basic types int and string only
func NewCodeLocation ¶
func NewCodeLocation(stackFramesToSkip int) (cl *CodeLocation)
NewCodeLocation gets data for a single stack frame
- for stackFramesToSkip 0, NewCodeLocation returns data for its immediate caller
func (*CodeLocation) Base ¶
func (cl *CodeLocation) Base() (baseName string)
Base returns base package name, an optional type name and the function name:
mains.(*Executable).AddErr
func (*CodeLocation) Dump ¶ added in v0.4.92
func (cl *CodeLocation) Dump() (s string)
Dump outputs all values quoted for debug purposes
File: "/opt/homebrew/Cellar/go/1.20.4/libexec/src/testing/testing.go" Line: 1576 FuncName: "testing.tRunner"
func (*CodeLocation) Full ¶
func (cl *CodeLocation) Full() (funcName string)
Full returns all available information on one line the function name, base filename and line number:
mains.(*Executable).AddErr-executable.go:25
func (*CodeLocation) FuncIdentifier ¶ added in v0.4.88
func (cl *CodeLocation) FuncIdentifier() (funcIdentifier string)
FuncIdentifier return the function name identifier “AddErr”
- no spaces
func (*CodeLocation) FuncLine ¶ added in v0.4.29
func (cl *CodeLocation) FuncLine() (funcLine string)
"github.com/haraldrudell/parl/mains.(*Executable).AddErr:43"
func (*CodeLocation) IsSet ¶ added in v0.4.25
func (cl *CodeLocation) IsSet() (isSet bool)
IsSet returns true if this CodeLocation has a value, ie. is not zero-value
func (*CodeLocation) Long ¶
func (cl *CodeLocation) Long() (funcName string)
Long returns full package path, an optional type name and the function name, base filename and line number:
mains.(*Executable).AddErr-executable.go:25
func (*CodeLocation) Name ¶
func (cl *CodeLocation) Name() (funcName string)
FuncName returns function name, characters no space:
AddErr
func (*CodeLocation) PackFunc ¶
func (cl *CodeLocation) PackFunc() (packageDotFunction string)
PackFunc return base package name and function “mains.AddErr”
func (*CodeLocation) Package ¶
func (cl *CodeLocation) Package() (packageName string)
Package return base package name, a single word of characters with no space:
mains
func (*CodeLocation) Short ¶
func (cl *CodeLocation) Short() (funcName string)
Short returns base package name, an optional type name and the function name, base filename and line number:
mains.(*Executable).AddErr-executable.go:25
func (CodeLocation) String ¶
func (cl CodeLocation) String() string
String returns a two-line string representation suitable for a multi-line stack trace. Typical output:
github.com/haraldrudell/parl/error116.(*TypeName).FuncName ␠␠/opt/sw/privates/parl/error116/codelocation_test.go:20
type StackSlice ¶ added in v0.4.6
type StackSlice []CodeLocation
StackSlice represents a StackSlice of program counters.
func NewStackSlice ¶ added in v0.4.6
func NewStackSlice(skip int) (slice StackSlice)
NewStackSlice returns a slice of stack frames for the current execution.
- if skip is 0, the caller of NewStackSlice is the first stack frame
- for skip argument less than 0, 0 is used
func (StackSlice) Clone ¶ added in v0.4.6
func (st StackSlice) Clone() (s StackSlice)
func (StackSlice) Format ¶ added in v0.4.6
func (st StackSlice) Format(s fmt.State, verb rune)
Format implements fmt.Formatter
func (StackSlice) Short ¶ added in v0.4.6
func (st StackSlice) Short() (s string)
func (StackSlice) String ¶ added in v0.4.6
func (st StackSlice) String() (s string)