Capture captures a stack trace of the specified depth, skipping the provided number of frames. skip=0 identifies the caller of Capture. The caller must call Free on the returned stacktrace after using it.
(skip int, depth Depth)
| 69 | // |
| 70 | // The caller must call Free on the returned stacktrace after using it. |
| 71 | func Capture(skip int, depth Depth) *Stack { |
| 72 | stack := _stackPool.Get() |
| 73 | |
| 74 | switch depth { |
| 75 | case First: |
| 76 | stack.pcs = stack.storage[:1] |
| 77 | case Full: |
| 78 | stack.pcs = stack.storage |
| 79 | } |
| 80 | |
| 81 | // Unlike other "skip"-based APIs, skip=0 identifies runtime.Callers |
| 82 | // itself. +2 to skip captureStacktrace and runtime.Callers. |
| 83 | numFrames := runtime.Callers( |
| 84 | skip+2, |
| 85 | stack.pcs, |
| 86 | ) |
| 87 | |
| 88 | // runtime.Callers truncates the recorded stacktrace if there is no |
| 89 | // room in the provided slice. For the full stack trace, keep expanding |
| 90 | // storage until there are fewer frames than there is room. |
| 91 | if depth == Full { |
| 92 | pcs := stack.pcs |
| 93 | for numFrames == len(pcs) { |
| 94 | pcs = make([]uintptr, len(pcs)*2) |
| 95 | numFrames = runtime.Callers(skip+2, pcs) |
| 96 | } |
| 97 | |
| 98 | // Discard old storage instead of returning it to the pool. |
| 99 | // This will adjust the pool size over time if stack traces are |
| 100 | // consistently very deep. |
| 101 | stack.storage = pcs |
| 102 | stack.pcs = pcs[:numFrames] |
| 103 | } else { |
| 104 | stack.pcs = stack.pcs[:numFrames] |
| 105 | } |
| 106 | |
| 107 | stack.frames = runtime.CallersFrames(stack.pcs) |
| 108 | return stack |
| 109 | } |
| 110 | |
| 111 | // Free releases resources associated with this stacktrace |
| 112 | // and returns it back to the pool. |