github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/agent/spy/spy.go (about)

     1  // Package spy contains an interface (Spy) and functionality to register new spies
     2  package spy
     3  
     4  import (
     5  	"fmt"
     6  	"github.com/pyroscope-io/pyroscope/pkg/agent/log"
     7  
     8  	"github.com/pyroscope-io/pyroscope/pkg/storage/metadata"
     9  )
    10  
    11  type Spy interface {
    12  	Stop() error
    13  	Snapshot(cb func(*Labels, []byte, uint64) error) error
    14  }
    15  
    16  type Resettable interface {
    17  	Reset()
    18  }
    19  
    20  type ProfileType string
    21  
    22  const (
    23  	ProfileCPU          ProfileType = "cpu"
    24  	ProfileInuseObjects ProfileType = "inuse_objects"
    25  	ProfileAllocObjects ProfileType = "alloc_objects"
    26  	ProfileInuseSpace   ProfileType = "inuse_space"
    27  	ProfileAllocSpace   ProfileType = "alloc_space"
    28  
    29  	Go     = "gospy"
    30  	EBPF   = "ebpfspy"
    31  	Python = "pyspy"
    32  	Ruby   = "rbspy"
    33  )
    34  
    35  func (t ProfileType) IsCumulative() bool {
    36  	return t == ProfileAllocObjects || t == ProfileAllocSpace
    37  }
    38  
    39  func (t ProfileType) Units() metadata.Units {
    40  	if t == ProfileInuseObjects || t == ProfileAllocObjects {
    41  		return metadata.ObjectsUnits
    42  	}
    43  	if t == ProfileInuseSpace || t == ProfileAllocSpace {
    44  		return metadata.BytesUnits
    45  	}
    46  
    47  	return metadata.SamplesUnits
    48  }
    49  
    50  func (t ProfileType) AggregationType() metadata.AggregationType {
    51  	if t == ProfileInuseObjects || t == ProfileInuseSpace {
    52  		return metadata.AverageAggregationType
    53  	}
    54  
    55  	return metadata.SumAggregationType
    56  }
    57  
    58  // TODO: this interface is not the best as different spies have different arguments
    59  type InitParams struct {
    60  	Pid           int
    61  	ProfileType   ProfileType
    62  	SampleRate    uint32
    63  	DisableGCRuns bool
    64  	Logger        log.Logger
    65  	PHPSpyArgs    string
    66  }
    67  type SpyIntitializer func(InitParams) (Spy, error)
    68  
    69  var (
    70  	supportedSpiesMap map[string]SpyIntitializer
    71  	SupportedSpies    []string
    72  )
    73  
    74  var autoDetectionMapping = map[string]string{
    75  	"php": "phpspy",
    76  
    77  	"dotnet": "dotnetspy",
    78  }
    79  
    80  func init() {
    81  	supportedSpiesMap = make(map[string]SpyIntitializer)
    82  }
    83  
    84  func RegisterSpy(name string, cb SpyIntitializer) {
    85  	SupportedSpies = append(SupportedSpies, name)
    86  	supportedSpiesMap[name] = cb
    87  }
    88  
    89  func StartFunc(name string) (SpyIntitializer, error) {
    90  	if s, ok := supportedSpiesMap[name]; ok {
    91  		return s, nil
    92  	}
    93  	return nil, fmt.Errorf("unknown spy \"%s\". Make sure it's supported (run `pyroscope version` to check if your version supports it)", name)
    94  }
    95  
    96  func ResolveAutoName(s string) string {
    97  	return autoDetectionMapping[s]
    98  }
    99  
   100  func SupportedExecSpies() []string {
   101  	supportedSpies := []string{}
   102  	for _, s := range SupportedSpies {
   103  		if s != Go {
   104  			supportedSpies = append(supportedSpies, s)
   105  		}
   106  	}
   107  
   108  	return supportedSpies
   109  }