github.com/pachyderm/pachyderm@v1.13.4/src/server/debug/cmds/cmds.go (about)

     1  package cmds
     2  
     3  import (
     4  	"os"
     5  	"time"
     6  
     7  	"github.com/gogo/protobuf/types"
     8  	"github.com/pachyderm/pachyderm/src/client"
     9  	"github.com/pachyderm/pachyderm/src/client/debug"
    10  	"github.com/pachyderm/pachyderm/src/client/pkg/errors"
    11  	"github.com/pachyderm/pachyderm/src/client/pps"
    12  	"github.com/pachyderm/pachyderm/src/server/pkg/cmdutil"
    13  	"github.com/spf13/cobra"
    14  )
    15  
    16  // Cmds returns a slice containing debug commands.
    17  func Cmds() []*cobra.Command {
    18  	var commands []*cobra.Command
    19  
    20  	var duration time.Duration
    21  	var pachd bool
    22  	var pipeline string
    23  	var worker string
    24  	profile := &cobra.Command{
    25  		Use:   "{{alias}} <profile> <file>",
    26  		Short: "Collect a set of pprof profiles.",
    27  		Long:  "Collect a set of pprof profiles.",
    28  		Run: cmdutil.RunFixedArgs(2, func(args []string) error {
    29  			client, err := client.NewOnUserMachine("debug-profile")
    30  			if err != nil {
    31  				return err
    32  			}
    33  			defer client.Close()
    34  			var d *types.Duration
    35  			if duration != 0 {
    36  				d = types.DurationProto(duration)
    37  			}
    38  			p := &debug.Profile{
    39  				Name:     args[0],
    40  				Duration: d,
    41  			}
    42  			filter, err := createFilter(pachd, pipeline, worker)
    43  			if err != nil {
    44  				return err
    45  			}
    46  			return withFile(args[1], func(f *os.File) error {
    47  				return client.Profile(p, filter, f)
    48  			})
    49  		}),
    50  	}
    51  	profile.Flags().DurationVarP(&duration, "duration", "d", time.Minute, "Duration to run a CPU profile for.")
    52  	profile.Flags().BoolVar(&pachd, "pachd", false, "Only collect the profile from pachd.")
    53  	profile.Flags().StringVarP(&pipeline, "pipeline", "p", "", "Only collect the profile from the worker pods for the given pipeline.")
    54  	profile.Flags().StringVarP(&worker, "worker", "w", "", "Only collect the profile from the given worker pod.")
    55  	commands = append(commands, cmdutil.CreateAlias(profile, "debug profile"))
    56  
    57  	binary := &cobra.Command{
    58  		Use:   "{{alias}} <file>",
    59  		Short: "Collect a set of binaries.",
    60  		Long:  "Collect a set of binaries.",
    61  		Run: cmdutil.RunFixedArgs(1, func(args []string) error {
    62  			client, err := client.NewOnUserMachine("debug-binary")
    63  			if err != nil {
    64  				return err
    65  			}
    66  			defer client.Close()
    67  			filter, err := createFilter(pachd, pipeline, worker)
    68  			if err != nil {
    69  				return err
    70  			}
    71  			return withFile(args[0], func(f *os.File) error {
    72  				return client.Binary(filter, f)
    73  			})
    74  		}),
    75  	}
    76  	binary.Flags().BoolVar(&pachd, "pachd", false, "Only collect the binary from pachd.")
    77  	binary.Flags().StringVarP(&pipeline, "pipeline", "p", "", "Only collect the binary from the worker pods for the given pipeline.")
    78  	binary.Flags().StringVarP(&worker, "worker", "w", "", "Only collect the binary from the given worker pod.")
    79  	commands = append(commands, cmdutil.CreateAlias(binary, "debug binary"))
    80  
    81  	var limit int64
    82  	dump := &cobra.Command{
    83  		Use:   "{{alias}} <file>",
    84  		Short: "Collect a standard set of debugging information.",
    85  		Long:  "Collect a standard set of debugging information.",
    86  		Run: cmdutil.RunFixedArgs(1, func(args []string) error {
    87  			client, err := client.NewOnUserMachine("debug-dump")
    88  			if err != nil {
    89  				return err
    90  			}
    91  			defer client.Close()
    92  			filter, err := createFilter(pachd, pipeline, worker)
    93  			if err != nil {
    94  				return err
    95  			}
    96  			return withFile(args[0], func(f *os.File) error {
    97  				return client.Dump(filter, limit, f)
    98  			})
    99  		}),
   100  	}
   101  	dump.Flags().BoolVar(&pachd, "pachd", false, "Only collect the dump from pachd.")
   102  	dump.Flags().StringVarP(&pipeline, "pipeline", "p", "", "Only collect the dump from the worker pods for the given pipeline.")
   103  	dump.Flags().StringVarP(&worker, "worker", "w", "", "Only collect the dump from the given worker pod.")
   104  	dump.Flags().Int64VarP(&limit, "limit", "l", 0, "Limit sets the limit for the number of commits / jobs that are returned for each repo / pipeline in the dump.")
   105  	commands = append(commands, cmdutil.CreateAlias(dump, "debug dump"))
   106  
   107  	debug := &cobra.Command{
   108  		Short: "Debug commands for analyzing a running cluster.",
   109  		Long:  "Debug commands for analyzing a running cluster.",
   110  	}
   111  	commands = append(commands, cmdutil.CreateAlias(debug, "debug"))
   112  
   113  	return commands
   114  }
   115  
   116  func createFilter(pachd bool, pipeline, worker string) (*debug.Filter, error) {
   117  	var f *debug.Filter
   118  	if pachd {
   119  		f = &debug.Filter{Filter: &debug.Filter_Pachd{Pachd: true}}
   120  	}
   121  	if pipeline != "" {
   122  		if f != nil {
   123  			return nil, errors.Errorf("only one debug filter allowed")
   124  		}
   125  		f = &debug.Filter{Filter: &debug.Filter_Pipeline{&pps.Pipeline{Name: pipeline}}}
   126  	}
   127  	if worker != "" {
   128  		if f != nil {
   129  			return nil, errors.Errorf("only one debug filter allowed")
   130  		}
   131  		f = &debug.Filter{Filter: &debug.Filter_Worker{&debug.Worker{Pod: worker}}}
   132  	}
   133  	return f, nil
   134  }
   135  
   136  func withFile(file string, cb func(*os.File) error) (retErr error) {
   137  	f, err := os.Create(file)
   138  	if err != nil {
   139  		return err
   140  	}
   141  	defer func() {
   142  		if err := f.Close(); retErr == nil {
   143  			retErr = err
   144  		}
   145  	}()
   146  	return cb(f)
   147  }