github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/convert/profile/profile.go (about) 1 package profile 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 8 "github.com/pyroscope-io/pyroscope/pkg/convert" 9 "github.com/pyroscope-io/pyroscope/pkg/ingestion" 10 "github.com/pyroscope-io/pyroscope/pkg/storage" 11 "github.com/pyroscope-io/pyroscope/pkg/storage/tree" 12 "github.com/pyroscope-io/pyroscope/pkg/structs/transporttrie" 13 ) 14 15 type RawProfile struct { 16 Format ingestion.Format 17 RawData []byte 18 } 19 20 func (p *RawProfile) Bytes() ([]byte, error) { return p.RawData, nil } 21 22 func (*RawProfile) ContentType() string { return "binary/octet-stream" } 23 24 func (p *RawProfile) Parse(ctx context.Context, putter storage.Putter, exporter storage.MetricsExporter, md ingestion.Metadata) error { 25 input := &storage.PutInput{ 26 StartTime: md.StartTime, 27 EndTime: md.EndTime, 28 Key: md.Key, 29 SpyName: md.SpyName, 30 SampleRate: md.SampleRate, 31 Units: md.Units, 32 AggregationType: md.AggregationType, 33 Val: tree.New(), 34 } 35 36 cb := createParseCallback(input, exporter) 37 r := bytes.NewReader(p.RawData) 38 var err error 39 switch p.Format { 40 case ingestion.FormatTrie: 41 err = transporttrie.IterateRaw(r, make([]byte, 0, 256), cb) 42 case ingestion.FormatTree: 43 err = convert.ParseTreeNoDict(r, cb) 44 case ingestion.FormatLines: 45 err = convert.ParseIndividualLines(r, cb) 46 case ingestion.FormatGroups: 47 err = convert.ParseGroups(r, cb) 48 default: 49 return fmt.Errorf("unknown format %q", p.Format) 50 } 51 52 if err != nil { 53 return err 54 } 55 56 if err = putter.Put(ctx, input); err != nil { 57 return ingestion.Error{Err: err} 58 } 59 60 return nil 61 } 62 63 func createParseCallback(pi *storage.PutInput, e storage.MetricsExporter) func([]byte, int) { 64 o, ok := e.Evaluate(pi) 65 if !ok { 66 return pi.Val.InsertInt 67 } 68 return func(k []byte, v int) { 69 o.Observe(k, v) 70 pi.Val.InsertInt(k, v) 71 } 72 }