blob: 331e07088981b146f2b8cb9323d0b93cc82aec99 [file] [edit]
// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package checks
import (
"bytes"
"fmt"
"strings"
"github.com/maruel/panicparse/stack"
)
func calcLengths(buckets stack.Buckets) (int, int) {
srcLen := 0
pkgLen := 0
for _, bucket := range buckets {
for _, line := range bucket.Signature.Stack.Calls {
l := len(line.SourceLine())
if l > srcLen {
srcLen = l
}
l = len(line.Func.PkgName())
if l > pkgLen {
pkgLen = l
}
}
}
return srcLen, pkgLen
}
func prettyStack(r *stack.Signature, srcLen, pkgLen int) string {
out := []string{}
for _, line := range r.Stack.Calls {
s := fmt.Sprintf(
" %-*s %-*s %s(%s)",
pkgLen, line.Func.PkgName(), srcLen, line.SourceLine(), line.Func.Name(),
line.Args)
out = append(out, s)
}
if r.Stack.Elided {
out = append(out, " (...)")
}
return strings.Join(out, "\n")
}
func processStackTrace(data string) string {
out := &bytes.Buffer{}
goroutines, err := stack.ParseDump(bytes.NewBufferString(data), out)
if err != nil || len(goroutines) == 0 {
return data
}
buckets := stack.SortBuckets(stack.Bucketize(goroutines, stack.AnyPointer))
srcLen, pkgLen := calcLengths(buckets)
for _, bucket := range buckets {
extra := ""
created := bucket.CreatedBy.Func.PkgDotName()
if created != "" {
if srcName := bucket.CreatedBy.SourceLine(); srcName != "" {
created += " @ " + srcName
}
extra += " [Created by " + created + "]"
}
fmt.Fprintf(out, "%d: %s%s\n", len(bucket.Routines), bucket.State, extra)
fmt.Fprintf(out, "%s\n", prettyStack(&bucket.Signature, srcLen, pkgLen))
}
return out.String()
}