Skip to content

Commit 9316aeb

Browse files
authored
add NewStack(), which generates a stack trace
2 parents 40f80a1 + 5dc497e commit 9316aeb

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

stack.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,13 @@ func (s *stack) StackTrace() StackTrace {
137137
}
138138

139139
func callers() *stack {
140+
return callersSkip(4)
141+
}
142+
143+
func callersSkip(skip int) *stack {
140144
const depth = 32
141145
var pcs [depth]uintptr
142-
n := runtime.Callers(3, pcs[:])
146+
n := runtime.Callers(skip, pcs[:])
143147
var st stack = pcs[0:n]
144148
return &st
145149
}
@@ -151,3 +155,16 @@ func funcname(name string) string {
151155
i = strings.Index(name, ".")
152156
return name[i+1:]
153157
}
158+
159+
// NewStack is for library implementers that want to generate a stack trace.
160+
// Normally you should insted use AddStack to get an error with a stack trace.
161+
//
162+
// The result of this function can be turned into a stack trace by calling .StackTrace()
163+
//
164+
// This function takes an argument for the number of stack frames to skip.
165+
// This avoids putting stack generation function calls like this one in the stack trace.
166+
// A value of 0 will give you the line that called NewStack(0)
167+
// A library author wrapping this in their own function will want to use a value of at least 1.
168+
func NewStack(skip int) StackTracer {
169+
return callersSkip(skip + 3)
170+
}

stack_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,12 @@ func TestStackTrace(t *testing.T) {
204204
}
205205
}
206206

207+
// This comment helps to maintain original line numbers
208+
// Perhaps this test is too fragile :)
207209
func stackTrace() StackTrace {
208-
const depth = 8
209-
var pcs [depth]uintptr
210-
n := runtime.Callers(1, pcs[:])
211-
var st stack = pcs[0:n]
212-
return st.StackTrace()
210+
return NewStack(0).StackTrace()
211+
// This comment helps to maintain original line numbers
212+
// Perhaps this test is too fragile :)
213213
}
214214

215215
func TestStackTraceFormat(t *testing.T) {
@@ -275,3 +275,15 @@ func TestStackTraceFormat(t *testing.T) {
275275
testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want)
276276
}
277277
}
278+
279+
func TestNewStack(t *testing.T) {
280+
got := NewStack(1).StackTrace()
281+
want := NewStack(1).StackTrace()
282+
if got[0] != want[0] {
283+
t.Errorf("NewStack(remove NewStack): want: %v, got: %v", want, got)
284+
}
285+
gotFirst := fmt.Sprintf("%+v", got[0])[0:15]
286+
if gotFirst != "testing.tRunner" {
287+
t.Errorf("NewStack(): want: %v, got: %+v", "testing.tRunner", gotFirst)
288+
}
289+
}

0 commit comments

Comments
 (0)