Documentation
¶
Index ¶
- Variables
- func Check(timeout time.Duration, ignores ...Ignore) error
- func CheckLeak(t T, timeout time.Duration, ignores ...Ignore)
- func CheckMainLeak(m M, timeout time.Duration, ignores ...Ignore)
- func CheckWithContext(ctx context.Context, ignores ...Ignore) error
- func Signal(signals ...os.Signal) context.Context
- func Timeout(d time.Duration) context.Context
- type Ignore
- type M
- type Stack
- type T
- type Trace
- type Traces
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var Backoff = func(t time.Duration) time.Duration { const maxSleep = 300 * time.Millisecond if t == 0 { return time.Microsecond } t *= 2 if t > maxSleep { return maxSleep } return t }
Backoff is the default algorithm for sleep backoff
var Exit = os.Exit
Exit to os.Exit
var GetStack = func(all bool) string { for i := 1024 * 1024; ; i *= 2 { buf := make([]byte, i) if n := runtime.Stack(buf, all); n < i { return string(buf[:n-1]) } } }
GetStack of current runtime
var TraceAncestorsEnabled = regexp.MustCompile(`tracebackancestors=\d+`).MatchString(os.Getenv("GODEBUG"))
TraceAncestorsEnabled returns true if GODEBUG="tracebackancestors=N" is set
Functions ¶
func CheckLeak ¶ added in v0.5.1
CheckLeak reports error if the test is leaking goroutine. Default timeout is 3s. Default ignore is gotrace.IgnoreNonChildren() .
func CheckMainLeak ¶ added in v0.5.1
CheckMainLeak reports error if goroutines are leaking after all tests are done. Default timeout is 3s. It's powerful but less accurate than Check, if you only use CheckMainLeak it will be hard to tell which test is the cause of the leak.
func CheckWithContext ¶ added in v0.6.0
CheckWithContext if there's goroutine leak
func Signal ¶ added in v0.1.1
Signal to cancel the returned context, default signal is CTRL+C .
Example ¶
package main import ( "fmt" "os" "runtime" "strings" "time" "github.com/ysmood/gotrace" ) func main() { // Skip the test for Windows because it can't send signal programatically. if runtime.GOOS == "windows" { fmt.Println("true") return } go func() { traces := gotrace.Wait(gotrace.Signal()) fmt.Println(strings.Contains(traces.String(), "gotrace_test.ExampleSignal")) }() time.Sleep(100 * time.Millisecond) p, _ := os.FindProcess(os.Getpid()) _ = p.Signal(os.Interrupt) time.Sleep(100 * time.Millisecond) }
Output: true
Types ¶
type Ignore ¶
Ignore returns true to ignore t
func CombineIgnores ¶
CombineIgnores into one
Example ¶
package main import ( "context" "fmt" "strings" "time" "github.com/ysmood/gotrace" ) func main() { ignore := gotrace.CombineIgnores( gotrace.IgnoreCurrent(), func(t *gotrace.Trace) bool { return strings.Contains(t.Raw, "ExampleCombineIgnores.func2") }, ) go func() { time.Sleep(2 * time.Second) }() go func() { time.Sleep(time.Second) }() start := time.Now() gotrace.Wait(context.TODO(), ignore) end := time.Since(start) if time.Second < end && end < 2*time.Second { fmt.Println("only waits for the second goroutine") } }
Output: only waits for the second goroutine
func IgnoreCurrent ¶
func IgnoreCurrent() Ignore
IgnoreCurrent running goroutines
Example ¶
package main import ( "context" "fmt" "time" "github.com/ysmood/gotrace" ) func main() { ignore := gotrace.IgnoreCurrent() go func() { time.Sleep(time.Second) }() start := time.Now() gotrace.Wait(context.TODO(), ignore) end := time.Since(start) if end > time.Second { fmt.Println("waited for 1 second") } }
Output: waited for 1 second
func IgnoreFuncs ¶
IgnoreFuncs ignores a Trace if it's first Stack's Func equals one of the names.
Example ¶
package main import ( "context" "fmt" "time" "github.com/ysmood/gotrace" ) func main() { ignoreCurrent := gotrace.IgnoreCurrent() ignore := gotrace.IgnoreFuncs("internal/poll.runtime_pollWait") go func() { time.Sleep(time.Second) }() start := time.Now() gotrace.Wait(context.TODO(), ignore, ignoreCurrent) end := time.Since(start) if end > time.Second { fmt.Println("waited for 1 second") } }
Output: waited for 1 second
func IgnoreNonChildren ¶ added in v0.5.0
func IgnoreNonChildren() Ignore
IgnoreNonChildren goroutines
type T ¶ added in v0.3.0
type T interface { Helper() Fail() Failed() bool Cleanup(f func()) Logf(format string, args ...interface{}) }
T interface for testing.T
type Trace ¶
type Trace struct { Raw string GoroutineID int64 GoroutineAncestorIDs []int64 // Need GODEBUG="tracebackancestors=N" to be set WaitReason string // https://github.com/golang/go/blob/874b3132a84cf76da6a48978826c04c380a37a50/src/runtime/runtime2.go#L997 Stacks []Stack // contains filtered or unexported fields }
Trace of one goroutine
type Traces ¶
type Traces []*Trace
Traces of goroutines
func Get ¶
Get the Trace of the calling goroutine. If all is true, all other goroutines' Traces will be appended into the result too.
Example ¶
package main import ( "fmt" "github.com/ysmood/gotrace" ) func main() { list := gotrace.Get(true) fmt.Println("id of current:", list[0].GoroutineID) fmt.Println("caller of current:", list[0].Stacks[2].Func) }
Output: id of current: 1 caller of current: github.com/ysmood/gotrace_test.ExampleGet
func WaitWithBackoff ¶ added in v0.5.1
func WaitWithBackoff(ctx context.Context, backoff func(time.Duration) time.Duration, ignores ...Ignore) (remain Traces)
WaitWithBackoff algorithm. Wait for other goroutines that are not ignored to exit. It returns the ones that are still active. It keeps counting the active goroutines that are not ignored, if the number is zero return.
func (Traces) String ¶ added in v0.1.0
String interface for fmt. It will merge similar trace together and print counts.
Example ¶
package main import ( "fmt" "strings" "time" "github.com/ysmood/gotrace" ) func main() { go func() { time.Sleep(time.Second) }() traces := gotrace.Wait(gotrace.Timeout(0)) str := fmt.Sprintf("%v %v", traces[0], traces) fmt.Println(strings.Contains(str, "gotrace_test.ExampleTraces_String")) }
Output: true