github.com/grafana/pyroscope@v1.18.0/pkg/og/convert/speedscope/speedscope_test.go (about) 1 package speedscope 2 3 import ( 4 "context" 5 "os" 6 7 . "github.com/onsi/ginkgo/v2" 8 . "github.com/onsi/gomega" 9 10 "github.com/grafana/pyroscope/api/model/labelset" 11 "github.com/grafana/pyroscope/pkg/og/ingestion" 12 "github.com/grafana/pyroscope/pkg/og/storage/metadata" 13 14 "github.com/grafana/pyroscope/pkg/og/storage" 15 ) 16 17 type mockIngester struct{ actual []*storage.PutInput } 18 19 func (m *mockIngester) Put(_ context.Context, p *storage.PutInput) error { 20 m.actual = append(m.actual, p) 21 return nil 22 } 23 24 func findInputByLabel(inputs []*storage.PutInput, normalizedLabel string) *storage.PutInput { 25 for _, in := range inputs { 26 if in.LabelSet.Normalized() == normalizedLabel { 27 return in 28 } 29 } 30 return nil 31 } 32 33 var _ = Describe("Speedscope", func() { 34 It("Can parse an event-format profile", func() { 35 data, err := os.ReadFile("testdata/simple.speedscope.json") 36 Expect(err).ToNot(HaveOccurred()) 37 38 key, err := labelset.Parse("foo") 39 Expect(err).ToNot(HaveOccurred()) 40 41 ingester := new(mockIngester) 42 profile := &RawProfile{RawData: data} 43 44 md := ingestion.Metadata{LabelSet: key, SampleRate: 100} 45 err = profile.Parse(context.Background(), ingester, nil, md) 46 Expect(err).ToNot(HaveOccurred()) 47 48 Expect(ingester.actual).To(HaveLen(1)) 49 input := ingester.actual[0] 50 51 Expect(input.Units).To(Equal(metadata.SamplesUnits)) 52 Expect(input.LabelSet.Normalized()).To(Equal("foo{profile_name=simple.txt}")) 53 expectedResult := `a;b 500 54 a;b;c 500 55 a;b;d 400 56 ` 57 Expect(input.Val.String()).To(Equal(expectedResult)) 58 Expect(input.SampleRate).To(Equal(uint32(10000))) 59 }) 60 61 It("Can parse a sample-format profile", func() { 62 data, err := os.ReadFile("testdata/two-sampled.speedscope.json") 63 Expect(err).ToNot(HaveOccurred()) 64 65 key, err := labelset.Parse("foo{x=y}") 66 Expect(err).ToNot(HaveOccurred()) 67 68 ingester := new(mockIngester) 69 profile := &RawProfile{RawData: data} 70 71 md := ingestion.Metadata{LabelSet: key, SampleRate: 100} 72 err = profile.Parse(context.Background(), ingester, nil, md) 73 Expect(err).ToNot(HaveOccurred()) 74 75 Expect(ingester.actual).To(HaveLen(2)) 76 77 input := findInputByLabel(ingester.actual, "foo.seconds{profile_name=one,x=y}") 78 Expect(input).ToNot(BeNil()) 79 Expect(input.Units).To(Equal(metadata.SamplesUnits)) 80 Expect(input.LabelSet.Normalized()).To(Equal("foo.seconds{profile_name=one,x=y}")) 81 expectedResult := `a;b 500 82 a;b;c 500 83 a;b;d 400 84 ` 85 Expect(input.Val.String()).To(Equal(expectedResult)) 86 Expect(input.SampleRate).To(Equal(uint32(100))) 87 88 input2 := findInputByLabel(ingester.actual, "foo.seconds{profile_name=two,x=y}") 89 Expect(input2).ToNot(BeNil()) 90 Expect(input2.Units).To(Equal(metadata.SamplesUnits)) 91 Expect(input2.LabelSet.Normalized()).To(Equal("foo.seconds{profile_name=two,x=y}")) 92 Expect(input2.Val.String()).To(Equal(expectedResult)) 93 Expect(input2.SampleRate).To(Equal(uint32(100))) 94 }) 95 96 It("Merges duplicate profiles", func() { 97 data, err := os.ReadFile("testdata/duplicates.speedscope.json") 98 Expect(err).ToNot(HaveOccurred()) 99 100 key, err := labelset.Parse("foo{x=y}") 101 Expect(err).ToNot(HaveOccurred()) 102 103 ingester := new(mockIngester) 104 profile := &RawProfile{RawData: data} 105 106 md := ingestion.Metadata{LabelSet: key, SampleRate: 100} 107 err = profile.Parse(context.Background(), ingester, nil, md) 108 Expect(err).ToNot(HaveOccurred()) 109 110 // Three profiles merged in to one 111 Expect(ingester.actual).To(HaveLen(1)) 112 113 input := ingester.actual[0] 114 Expect(input.Units).To(Equal(metadata.SamplesUnits)) 115 // Note that profiles with different `endValue`s are merged 116 // since `endValue` not represented in pprof 117 Expect(input.LabelSet.Normalized()).To(Equal("foo{profile_name=one,x=y}")) 118 expectedResult := `a;b 1500 119 a;b;c 1500 120 a;b;d 1200 121 ` 122 Expect(input.Val.String()).To(Equal(expectedResult)) 123 Expect(input.SampleRate).To(Equal(uint32(100))) 124 }) 125 })