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  }