github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/helper/profile/meta.go (about)

     1  // Copyright 2023 iLogtail Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package profile
    16  
    17  import (
    18  	"context"
    19  	"strings"
    20  	"time"
    21  
    22  	"github.com/gofrs/uuid"
    23  
    24  	"github.com/alibaba/ilogtail/pkg/protocol"
    25  )
    26  
    27  type Input struct {
    28  	Profile  RawProfile
    29  	Metadata Meta
    30  }
    31  
    32  type Stack struct {
    33  	Name  string
    34  	Stack []string
    35  }
    36  
    37  type Type struct {
    38  	Name string
    39  	Kind string
    40  }
    41  
    42  var (
    43  	CPUType       = Type{Name: "cpu", Kind: "profile_cpu"}
    44  	MemType       = Type{Name: "mem", Kind: "profile_mem"}
    45  	MutexType     = Type{Name: "mutex", Kind: "profile_mutex"}
    46  	BlockType     = Type{Name: "block", Kind: "profile_block"}
    47  	ExceptionType = Type{Name: "exception", Kind: "profile_exception"}
    48  	GoroutineType = Type{Name: "goroutines", Kind: "profile_goroutines"}
    49  	UnknownType   = Type{Name: "unknown", Kind: "profile_unknown"}
    50  )
    51  
    52  func IsLegalType(t Type) bool {
    53  	switch t {
    54  	case CPUType, MemType, MutexType, BlockType, ExceptionType, GoroutineType:
    55  		return true
    56  	default:
    57  		return false
    58  	}
    59  }
    60  
    61  type Format string
    62  
    63  type CallbackFunc func(id uint64, stack *Stack, vals []uint64, types, units, aggs []string, startTime, endTime int64, labels map[string]string)
    64  
    65  const (
    66  	FormatPprof      Format = "pprof"
    67  	FormatJFR        Format = "jfr"
    68  	FormatTrie       Format = "trie"
    69  	FormatTree       Format = "tree"
    70  	FormatLines      Format = "lines"
    71  	FormatGroups     Format = "groups"
    72  	FormatSpeedscope Format = "speedscope"
    73  )
    74  
    75  type Meta struct {
    76  	StartTime       time.Time
    77  	EndTime         time.Time
    78  	Tags            map[string]string
    79  	SpyName         string
    80  	SampleRate      uint32
    81  	Units           Units
    82  	AggregationType AggType
    83  }
    84  
    85  type AggType string
    86  
    87  const (
    88  	AvgAggType AggType = "avg"
    89  	SumAggType AggType = "sum"
    90  )
    91  
    92  type Units string
    93  
    94  const (
    95  	SamplesUnits         Units = "samples"
    96  	NanosecondsUnit      Units = "nanoseconds"
    97  	ObjectsUnit          Units = "objects"
    98  	BytesUnit            Units = "bytes"
    99  	GoroutinesUnits      Units = "goroutines"
   100  	LockNanosecondsUnits Units = "lock_nanoseconds"
   101  	LockSamplesUnits     Units = "lock_samples"
   102  )
   103  
   104  func DetectProfileType(valType string) Type {
   105  	switch valType {
   106  	case "inuse_space", "inuse_objects", "alloc_space", "alloc_objects", "alloc-size", "alloc-samples", "alloc_in_new_tlab_objects", "alloc_in_new_tlab_bytes", "alloc_outside_tlab_objects", "alloc_outside_tlab_bytes":
   107  		return MemType
   108  	case "samples", "cpu", "itimer", "lock_count", "lock_duration", "wall":
   109  		return CPUType
   110  	case "mutex_count", "mutex_duration", "block_duration", "block_count", "contentions", "delay", "lock-time", "lock-count":
   111  		return MutexType
   112  	case "goroutines", "goroutine":
   113  		return GoroutineType
   114  	case "exception":
   115  		return ExceptionType
   116  	default:
   117  		return UnknownType
   118  	}
   119  }
   120  
   121  func GetProfileID(meta *Meta) string {
   122  	var profileIDStr string
   123  	if id, ok := meta.Tags["profile_id"]; ok {
   124  		profileIDStr = id
   125  	} else {
   126  		profileID, _ := uuid.NewV4()
   127  		profileIDStr = profileID.String()
   128  	}
   129  	return profileIDStr
   130  }
   131  
   132  type FormatType string
   133  
   134  // SequenceMapping demo
   135  // nodejs: ./node_modules/express/lib/router/index.js:process_params:338 /app/node_modules/express/lib/router/index.js
   136  // golang: compress/flate.NewWriter /usr/local/go/src/compress/flate/deflate.go
   137  // rust: backtrace_rs.rs:23 - <pprof::backtrace::backtrace_rs::Trace as pprof::backtrace::Trace>::trace
   138  // dotnet: System.Threading.Tasks!Task.InternalWaitCore System.Private.CoreLib
   139  // ruby: /usr/local/bundle/gems/pyroscope-0.3.0-x86_64-linux/lib/pyroscope.rb:63 - tag_wrapper
   140  // python: lib/utility/utility.py:38 - find_nearest_vehicle
   141  // java: libjvm.so.AdvancedThresholdPolicy::method_back_branch_event
   142  // ebpf: /usr/lib/systemd/systemd+0x93242
   143  // php: <internal> - sleep
   144  var sequenceMapping = map[FormatType]SequenceType{
   145  	PyroscopeNodeJs: FunctionFirst,
   146  	PyroscopeGolang: FunctionFirst,
   147  	PyroscopeRust:   PosFirst,
   148  	PyroscopeDotnet: FunctionFirst,
   149  	PyroscopeRuby:   PosFirst,
   150  	PyroscopePython: PosFirst,
   151  	PyroscopeJava:   FunctionFirst,
   152  	PyroscopeEbpf:   FunctionFirst,
   153  	PyroscopePhp:    PosFirst,
   154  	Unknown:         FunctionFirst,
   155  }
   156  
   157  const (
   158  	PyroscopeNodeJs = "node"
   159  	PyroscopeGolang = "go"
   160  	PyroscopeRust   = "rs"
   161  	PyroscopeDotnet = "dotnet"
   162  	PyroscopeRuby   = "rb"
   163  	PyroscopePython = "py"
   164  	PyroscopeJava   = "java"
   165  	PyroscopeEbpf   = "ebpf"
   166  	PyroscopePhp    = "php"
   167  	Unknown         = "unknown"
   168  )
   169  
   170  type SequenceType int
   171  
   172  const (
   173  	_ SequenceType = iota
   174  	PosFirst
   175  	FunctionFirst
   176  )
   177  
   178  func FormatPositionAndName(str string, t FormatType) string {
   179  	str = strings.TrimSpace(str)
   180  	idx := strings.Index(str, " ")
   181  	if idx < 0 {
   182  		return str // means no position
   183  	}
   184  	joiner := func(name, pos string) string {
   185  		var b strings.Builder
   186  		b.Grow(len(name) + len(pos) + 1)
   187  		b.Write([]byte(name))
   188  		b.Write([]byte{' '})
   189  		b.Write([]byte(pos))
   190  		return b.String()
   191  	}
   192  	name := str[:idx]
   193  	idx = strings.LastIndex(str, " ")
   194  	pos := str[idx+1:]
   195  	sequenceType := sequenceMapping[t]
   196  	switch sequenceType {
   197  	case PosFirst:
   198  		return joiner(pos, name)
   199  	case FunctionFirst:
   200  		return joiner(name, pos)
   201  	default:
   202  		return str
   203  	}
   204  }
   205  
   206  func FormatPostionAndNames(strs []string, t FormatType) []string {
   207  	for i := range strs {
   208  		strs[i] = FormatPositionAndName(strs[i], t)
   209  	}
   210  	return strs
   211  }
   212  
   213  func (u Units) DetectValueType() string {
   214  	switch u {
   215  	case NanosecondsUnit, SamplesUnits:
   216  		return "cpu"
   217  	case ObjectsUnit, BytesUnit:
   218  		return "mem"
   219  	case GoroutinesUnits:
   220  		return "goroutines"
   221  	case LockSamplesUnits, LockNanosecondsUnits:
   222  		return "mutex"
   223  	}
   224  	return "unknown"
   225  }
   226  
   227  type RawProfile interface {
   228  	Parse(ctx context.Context, meta *Meta, tags map[string]string) (logs []*protocol.Log, err error)
   229  }