...
1
2
3
4
5
6 package stack
7
8 import (
9 "fmt"
10 "text/tabwriter"
11 )
12
13
14 type Dump []Goroutine
15
16
17 type Goroutine struct {
18 State string
19 ID int
20 Stack Stack
21 }
22
23
24 type Stack []Frame
25
26
27 type Frame struct {
28 Function Function
29 Position Position
30 }
31
32
33 type Function struct {
34 Package string
35 Type string
36 Name string
37 }
38
39
40 type Position struct {
41 Filename string
42 Line int
43 }
44
45
46 type Summary struct {
47 Total int
48 Calls []Call
49 }
50
51
52
53 type Call struct {
54 Stack Stack
55 Groups []Group
56 }
57
58
59 type Group struct {
60 State string
61 Goroutines []Goroutine
62 }
63
64
65 type Delta struct {
66 Before Dump
67 Shared Dump
68 After Dump
69 }
70
71 func (s Stack) equal(other Stack) bool {
72 if len(s) != len(other) {
73 return false
74 }
75 for i, frame := range s {
76 if !frame.equal(other[i]) {
77 return false
78 }
79 }
80 return true
81 }
82
83 func (s Stack) less(other Stack) bool {
84 for i, frame := 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
98 func (f Frame) equal(other Frame) bool {
99 return f.Position.equal(other.Position)
100 }
101
102 func (f Frame) less(other Frame) bool {
103 return f.Position.less(other.Position)
104 }
105
106 func (p Position) equal(other Position) bool {
107 return p.Filename == other.Filename && p.Line == other.Line
108 }
109
110 func (p Position) less(other Position) bool {
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
120 func (s Summary) Format(w fmt.State, r rune) {
121 tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
122 for i, c := range s.Calls {
123 if i > 0 {
124 fmt.Fprintf(tw, "\n\n")
125 tw.Flush()
126 }
127 fmt.Fprint(tw, c)
128 }
129 tw.Flush()
130 if s.Total > 0 && w.Flag('+') {
131 fmt.Fprintf(w, "\n\n%d goroutines, %d unique", s.Total, len(s.Calls))
132 }
133 }
134
135 func (c Call) Format(w fmt.State, r rune) {
136 for i, g := range c.Groups {
137 if i > 0 {
138 fmt.Fprint(w, " ")
139 }
140 fmt.Fprint(w, g)
141 }
142 for _, f := range c.Stack {
143 fmt.Fprintf(w, "\n%v", f)
144 }
145 }
146
147 func (g Group) Format(w fmt.State, r rune) {
148 fmt.Fprintf(w, "[%v]: ", g.State)
149 for i, gr := range g.Goroutines {
150 if i > 0 {
151 fmt.Fprint(w, ", ")
152 }
153 fmt.Fprintf(w, "$%d", gr.ID)
154 }
155 }
156
157 func (f Frame) Format(w fmt.State, c rune) {
158 fmt.Fprintf(w, "%v:\t%v", f.Position, f.Function)
159 }
160
161 func (f Function) Format(w fmt.State, c rune) {
162 if f.Type != "" {
163 fmt.Fprintf(w, "(%v).", f.Type)
164 }
165 fmt.Fprintf(w, "%v", f.Name)
166 }
167
168 func (p Position) Format(w fmt.State, c rune) {
169 fmt.Fprintf(w, "%v:%v", p.Filename, p.Line)
170 }
171
View as plain text