// Package profile provides an extension to generate profile data from k6 itself. // // An Output extension is used to leverage the Start and Stop hooks which are // otherwise inaccessible in a regular module. package profile import ( "fmt" "os" "runtime" "runtime/pprof" "go.k6.io/k6/metrics" "go.k6.io/k6/output" ) const ( cpuProfilePath = "cpu.prof" memProfilePath = "mem.prof" ) type profExt struct { cpuFile *os.File } func New(output.Params) (output.Output, error) { return &profExt{}, nil } func (*profExt) Description() string { return "profile" } func (ext *profExt) Start() error { var err error ext.cpuFile, err = os.Create(cpuProfilePath) if err != nil { return fmt.Errorf("creating cpu profile file: %v", err) } if err := pprof.StartCPUProfile(ext.cpuFile); err != nil { return fmt.Errorf("starting cpu profile: %v", err) } return nil } func (ext *profExt) Stop() error { pprof.StopCPUProfile() if err := ext.cpuFile.Close(); err != nil { return fmt.Errorf("closing cpu profile file: %v", err) } f, err := os.Create(memProfilePath) if err != nil { return fmt.Errorf("creating mem profile file: %v", err) } defer f.Close() runtime.GC() if err := pprof.WriteHeapProfile(f); err != nil { return fmt.Errorf("writing mem profile: %v", err) } return nil } func (*profExt) AddMetricSamples([]metrics.SampleContainer) {} func init() { output.RegisterExtension("profile", New) }