GoPLS Viewer

Home|gopls/internal/stack/stack.go
1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package stack provides support for parsing standard goroutine stack traces.
6package stack
7
8import (
9    "fmt"
10    "text/tabwriter"
11)
12
13// Dump is a raw set of goroutines and their stacks.
14type Dump []Goroutine
15
16// Goroutine is a single parsed goroutine dump.
17type Goroutine struct {
18    State string // state that the goroutine is in.
19    ID    int    // id of the goroutine.
20    Stack Stack  // call frames that make up the stack
21}
22
23// Stack is a set of frames in a callstack.
24type Stack []Frame
25
26// Frame is a point in a call stack.
27type Frame struct {
28    Function Function
29    Position Position
30}
31
32// Function is the function called at a frame.
33type Function struct {
34    Package string // package name of function if known
35    Type    string // if set function is a method of this type
36    Name    string // function name of the frame
37}
38
39// Position is the file position for a frame.
40type Position struct {
41    Filename string // source filename
42    Line     int    // line number within file
43}
44
45// Summary is a set of stacks processed and collated into Calls.
46type Summary struct {
47    Total int    // the total count of goroutines in the summary
48    Calls []Call // the collated stack traces
49}
50
51// Call is set of goroutines that all share the same callstack.
52// They will be grouped by state.
53type Call struct {
54    Stack  Stack   // the shared callstack information
55    Groups []Group // the sets of goroutines with the same state
56}
57
58// Group is a set of goroutines with the same stack that are in the same state.
59type Group struct {
60    State      string      // the shared state of the goroutines
61    Goroutines []Goroutine // the set of goroutines in this group
62}
63
64// Delta represents the difference between two stack dumps.
65type Delta struct {
66    Before Dump // The goroutines that were only in the before set.
67    Shared Dump // The goroutines that were in both sets.
68    After  Dump // The goroutines that were only in the after set.
69}
70
71func (s Stackequal(other Stackbool {
72    if len(s) != len(other) {
73        return false
74    }
75    for iframe := range s {
76        if !frame.equal(other[i]) {
77            return false
78        }
79    }
80    return true
81}
82
83func (s Stackless(other Stackbool {
84    for iframe := range s {
85        if i >= len(other) {
86            return false
87        }
88        if frame.less(other[i]) {
89            return true
90        }
91        if !frame.equal(other[i]) {
92            return false
93        }
94    }
95    return len(s) < len(other)
96}
97
98func (f Frameequal(other Framebool {
99    return f.Position.equal(other.Position)
100}
101
102func (f Frameless(other Framebool {
103    return f.Position.less(other.Position)
104}
105
106func (p Positionequal(other Positionbool {
107    return p.Filename == other.Filename && p.Line == other.Line
108}
109
110func (p Positionless(other Positionbool {
111    if p.Filename < other.Filename {
112        return true
113    }
114    if p.Filename > other.Filename {
115        return false
116    }
117    return p.Line < other.Line
118}
119
120func (s SummaryFormat(w fmt.Stater rune) {
121    tw := tabwriter.NewWriter(w001' '0)
122    for ic := range s.Calls {
123        if i > 0 {
124            fmt.Fprintf(tw"\n\n")
125            tw.Flush()
126        }
127        fmt.Fprint(twc)
128    }
129    tw.Flush()
130    if s.Total > 0 && w.Flag('+') {
131        fmt.Fprintf(w"\n\n%d goroutines, %d unique"s.Totallen(s.Calls))
132    }
133}
134
135func (c CallFormat(w fmt.Stater rune) {
136    for ig := range c.Groups {
137        if i > 0 {
138            fmt.Fprint(w" ")
139        }
140        fmt.Fprint(wg)
141    }
142    for _f := range c.Stack {
143        fmt.Fprintf(w"\n%v"f)
144    }
145}
146
147func (g GroupFormat(w fmt.Stater rune) {
148    fmt.Fprintf(w"[%v]: "g.State)
149    for igr := range g.Goroutines {
150        if i > 0 {
151            fmt.Fprint(w", ")
152        }
153        fmt.Fprintf(w"$%d"gr.ID)
154    }
155}
156
157func (f FrameFormat(w fmt.Statec rune) {
158    fmt.Fprintf(w"%v:\t%v"f.Positionf.Function)
159}
160
161func (f FunctionFormat(w fmt.Statec rune) {
162    if f.Type != "" {
163        fmt.Fprintf(w"(%v)."f.Type)
164    }
165    fmt.Fprintf(w"%v"f.Name)
166}
167
168func (p PositionFormat(w fmt.Statec rune) {
169    fmt.Fprintf(w"%v:%v"p.Filenamep.Line)
170}
171
MembersX
Call.Format.r
Goroutine.State
Goroutine.ID
Stack.equal.other
Stack.less.RangeStmt_2275.i
Frame.equal.other
Frame.less.f
Position.equal.other
Group.Format
Goroutine.Stack
Frame.Function
Stack.equal
Stack.less.other
Group.Format.w
Function
Function.Name
Call.Format.RangeStmt_3306.g
Group.Format.r
Function.Format
Position.Format.p
Call.Groups
Frame.Format.f
Position.Format
Goroutine
Frame.less
Summary.Format
Summary.Format.w
Call.Format.c
Frame.Format.w
Function.Format.w
Summary
Group.Goroutines
Stack.less.RangeStmt_2275.frame
Summary.Format.tw
Position.Format.c
Function.Type
Position.Line
Delta.Before
Frame.equal
Group.Format.g
Function.Format.c
Delta
Delta.Shared
Stack.equal.RangeStmt_2139.frame
Stack.less
Call.Format.RangeStmt_3397.f
Frame
Call.Format
Call.Stack
Call.Format.RangeStmt_3306.i
Frame.Format.c
Group.Format.RangeStmt_3540.i
Dump
Position.Filename
Summary.Total
Delta.After
Position.less
Summary.Format.r
Call.Format.w
Function.Format.f
Position.Format.w
tabwriter
Stack.equal.RangeStmt_2139.i
Position.equal
Position.less.p
Position.less.other
Frame.Format
Position
Summary.Format.RangeStmt_3029.i
Stack
Summary.Calls
Group
Group.State
Stack.equal.s
Stack.less.s
Frame.equal.f
Frame.Position
Function.Package
Call
Frame.less.other
Position.equal.p
Group.Format.RangeStmt_3540.gr
Summary.Format.s
Summary.Format.RangeStmt_3029.c
Members
X