github.com/grafana/pyroscope@v1.18.0/pkg/pprof/fix_go_truncated_test.go (about) 1 package pprof 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/grafana/pyroscope/pkg/pprof/testhelper" 12 ) 13 14 func Benchmark_RepairGoTruncatedStacktraces(b *testing.B) { 15 p, err := OpenFile("testdata/gotruncatefix/heap_go_truncated_3.pb.gz") 16 require.NoError(b, err) 17 b.ResetTimer() 18 b.ReportAllocs() 19 for i := 0; i < b.N; i++ { 20 RepairGoTruncatedStacktraces(FixGoProfile(p.CloneVT())) 21 } 22 } 23 24 func generateStackTrace(n int) []string { 25 res := make([]string, n) 26 runes := []rune("abcdefghijklmnopqrstuvwxyz") 27 28 for idx := range res { 29 dest := n - (idx + 1) 30 if idx == 0 { 31 res[dest] = "start" 32 continue 33 } 34 res[dest] = fmt.Sprintf("%c%d", runes[(idx-1)/10], (idx-1)%10) 35 } 36 return res 37 } 38 39 func Test_RepairGoTruncatedStacktraces(t *testing.T) { 40 n := 128 41 fullStack := generateStackTrace(n) 42 b := testhelper.NewProfileBuilder(0).CPUProfile() 43 b.ForStacktraceString(fullStack[n-24:]...).AddSamples(1) 44 b.ForStacktraceString(fullStack[n-58 : n-9]...).AddSamples(2) 45 b.ForStacktraceString(fullStack[n-57 : n-8]...).AddSamples(4) 46 b.ForStacktraceString(fullStack[n-56 : n-7]...).AddSamples(8) 47 b.ForStacktraceString(append([]string{"yy1"}, fullStack[n-22:]...)...).AddSamples(16) 48 49 RepairGoTruncatedStacktraces(b.Profile) 50 51 // ensure all stacktraces start with the same 8 location ids 52 stacks := make([]uint64, 8) 53 for idx, sample := range b.Sample { 54 first8Stacks := sample.LocationId[len(sample.LocationId)-8:] 55 if idx == 0 { 56 copy(stacks, first8Stacks) 57 continue 58 } 59 t.Log(stacks) 60 assert.Equal(t, stacks, first8Stacks) 61 } 62 } 63 64 func Test_UpdateFixtures_RepairGoTruncatedStacktraces(t *testing.T) { 65 if os.Getenv("UPDATE_FIXTURES") != "true" { 66 t.Skip() 67 } 68 t.Helper() 69 paths := []string{ 70 "testdata/gotruncatefix/heap_go_truncated_1.pb.gz", // Cortex. 71 "testdata/gotruncatefix/heap_go_truncated_2.pb.gz", // Cortex. 72 "testdata/gotruncatefix/heap_go_truncated_3.pb.gz", // Loki. Pathological. 73 "testdata/gotruncatefix/heap_go_truncated_4.pb.gz", // Pyroscope. 74 "testdata/gotruncatefix/cpu_go_truncated_1.pb.gz", // Cloudwatch Exporter 75 } 76 for _, path := range paths { 77 func() { 78 p, err := OpenFile(path) 79 require.NoError(t, err, path) 80 f, err := os.Create(path + ".fixed") 81 require.NoError(t, err, path) 82 defer f.Close() 83 p.Profile = FixGoProfile(p.Profile) 84 RepairGoTruncatedStacktraces(p.Profile) 85 _, err = p.WriteTo(f) 86 require.NoError(t, err, path) 87 }() 88 } 89 }