gostackparse

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 2, 2023 License: Apache-2.0, BSD-3-Clause, Apache-2.0 Imports: 8 Imported by: 47

README

ci test status documentation

gostackparse

Package gostackparse parses goroutines stack traces as produced by panic() or debug.Stack() at ~300 MiB/s.

Parsing this data can be useful for Goroutine Profiling or analyzing crashes from log files.

Usage

The package provides a simple Parse() API. You can use it like this:

import "github.com/DataDog/gostackparse"

func main() {
	// Get a text-based stack trace
	stack := debug.Stack()
	// Parse it
	goroutines, _ := gostackparse.Parse(bytes.NewReader(stack))
	// Ouptut the results
	json.NewEncoder(os.Stdout).Encode(goroutines)
}

The result is a simple list of Goroutine structs:

[
  {
    "ID": 1,
    "State": "running",
    "Wait": 0,
    "LockedToThread": false,
    "Stack": [
      {
        "Func": "runtime/debug.Stack",
        "File": "/usr/local/Cellar/go/1.16/libexec/src/runtime/debug/stack.go",
        "Line": 24
      },
      {
        "Func": "main.main",
        "File": "/home/go/src/github.com/DataDog/gostackparse/example/main.go",
        "Line": 18
      }
    ],
    "FramesElided": false,
    "CreatedBy": null
  }
]

Design Goals

  1. Safe: No panics should be thrown.
  2. Simple: Keep this pkg small and easy to modify.
  3. Forgiving: Favor producing partial results over no results, even if the input data is different than expected.
  4. Efficient: Parse several hundred MiB/s.

Testing

gostackparse has been tested using a combination of hand picked test-fixtures, property based testing, and fuzzing.

Comparsion to panicparse

panicparse is a popular library implementing similar functionality.

gostackparse was created to provide a subset of the functionality (only the parsing) using ~10x less code while achieving > 100x faster performance. If you like fast minimalistic code, you might prefer it. If you're looking for more features and a larger community, use panicparse.

Benchmarks

gostackparse includes a small benchmark that shows that it can parse test-fixtures/waitsince.txt at ~300 MiB/s and how that compares to panicparse.

$ cp panicparse_test.go.disabled panicparse_test.go
$ go get -t .
$ go test -bench .
goos: darwin
goarch: amd64
pkg: github.com/DataDog/gostackparse
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkGostackparse-12   45456    26275 ns/op 302.34 MiB/s   17243 B/op    306 allocs/op
BenchmarkPanicparse-12     76    15943320 ns/op   0.50 MiB/s 5274247 B/op 116049 allocs/op
PASS
ok  	github.com/DataDog/gostackparse	3.634s

License

This work is dual-licensed under Apache 2.0 or BSD3. See LICENSE.

Documentation

Overview

Package gostackparse parses goroutines stack traces as produced by panic() or debug.Stack() at ~300 MiB/s.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Frame

type Frame struct {
	// Func is the name of the function, including package name, e.g. "main.main"
	// or "net/http.(*Server).Serve".
	Func string
	// File is the absolute path of source file e.g.
	// "/go/src/example.org/example/main.go".
	File string
	// Line is the line number of inside of the source file that was active when
	// the sample was taken.
	Line int
}

Frame is a single call frame on the stack.

type Goroutine

type Goroutine struct {
	// ID is the goroutine id (aka `goid`).
	ID int
	// State is the `atomicstatus` of the goroutine, or if "waiting" the
	// `waitreason`.
	State string
	// Wait is the approximate duration a goroutine has been waiting or in a
	// syscall as determined by the first gc after the wait started. Aka
	// `waitsince`.
	Wait time.Duration
	// LockedToThread is true if the goroutine is locked by a thread, aka
	// `lockedm`.
	LockedToThread bool
	// Stack is the stack trace of the goroutine.
	Stack []*Frame
	// FramesElided is true if the stack trace contains a message indicating that
	// additional frames were elided. This happens when the stack depth exceeds
	// 100.
	FramesElided bool
	// CreatedBy is the frame that created this goroutine, nil for main().
	CreatedBy *Frame
	// Ancestors are the Goroutines that created this goroutine.
	// See GODEBUG=tracebackancestors=n in https://pkg.go.dev/runtime.
	Ancestor *Goroutine `json:"Ancestor,omitempty"`
}

Goroutine represents a single goroutine and its stack after extracting it from the runtime.Stack() text format. See [1] for more info. [1] https://github.com/felixge/go-profiler-notes/blob/main/goroutine.md

func Parse

func Parse(r io.Reader) ([]*Goroutine, []error)

Parse parses a goroutines stack trace dump as produced by runtime.Stack(). The parser is forgiving and will continue parsing even when encountering unexpected data. When this happens it will try to discard the entire goroutine that encountered the problem and continue with the next one. It will also return an error for every goroutine that couldn't be parsed. If all goroutines were parsed successfully, the []error slice is empty.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL