| 60 | ) |
| 61 | |
| 62 | func (c *cleaner) clean(stack string) string { |
| 63 | replacements := []string{ |
| 64 | normalizedStackPath(c.GOPATH), "<gopath>", |
| 65 | normalizedStackPath(c.GOROOT), "<goroot>", |
| 66 | } |
| 67 | |
| 68 | if pwd := c.PWD; len(pwd) > 0 { |
| 69 | replacements = append(replacements, normalizedStackPath(pwd), "<pwd>") |
| 70 | } |
| 71 | if home := c.HOME; len(home) > 0 { |
| 72 | replacements = append(replacements, normalizedStackPath(home), "<home>") |
| 73 | } |
| 74 | |
| 75 | stackPathReplacer := strings.NewReplacer(replacements...) |
| 76 | |
| 77 | // TODO: more nuanced replace for other known values like true/false, maybe empty string? |
| 78 | |
| 79 | stack = stackPathReplacer.Replace(stack) |
| 80 | stack = stackHexRegexp.ReplaceAllString(stack, "<hex>") |
| 81 | stack = stackNilRegexp.ReplaceAllString(stack, "<nil>") |
| 82 | stack = strings.TrimRight(stack, "\n") |
| 83 | |
| 84 | lines := strings.Split(string(stack), "\n") |
| 85 | // omit lines: 0 go routine, 2-3 stack call, 4-5 cleanup call |
| 86 | lines = lines[5:] |
| 87 | |
| 88 | for i, line := range lines { |
| 89 | if strings.Contains(line, "<goroot>") { |
| 90 | // for lines like: `<goroot>/src/runtime/debug/stack.go:24 +<hex>` |
| 91 | lines[i] = fmt.Sprintf("%s:<line> +<hex>", strings.Split(line, ":")[0]) |
| 92 | } |
| 93 | if strings.Contains(line, "in goroutine") { |
| 94 | lines[i] = fmt.Sprintf("%s in gouroutine <int>", strings.Split(line, " in goroutine ")[0]) |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | return strings.Join(lines, "\n") |
| 99 | } |
| 100 | func normalizedStackPath(path string) string { |
| 101 | return strings.ReplaceAll(path, string(os.PathSeparator), "/") |
| 102 | } |