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  }