debug: rename cluster target to members

The API is called members. Using the same name as the API should help describe the contents
of the file.
This commit is contained in:
Daniel Nephin 2021-08-06 13:30:32 -04:00
parent 251026e374
commit bbf6a94c9a
2 changed files with 69 additions and 56 deletions

View File

@ -114,7 +114,7 @@ func (c *cmd) init() {
fmt.Sprintf("One or more types of information to capture. This can be used "+
"to capture a subset of information, and defaults to capturing "+
"everything available. Possible information for capture: %s. "+
"This can be repeated multiple times.", strings.Join(c.defaultTargets(), ", ")))
"This can be repeated multiple times.", strings.Join(defaultTargets, ", ")))
c.flags.DurationVar(&c.interval, "interval", debugInterval,
fmt.Sprintf("The interval in which to capture dynamic information such as "+
"telemetry, and profiling. Defaults to %s.", debugInterval))
@ -195,7 +195,7 @@ func (c *cmd) Run(args []string) int {
}
// Capture dynamic information from the target agent, blocking for duration
if c.configuredTarget("metrics") || c.configuredTarget("logs") || c.configuredTarget("pprof") {
if c.captureTarget(targetMetrics) || c.captureTarget(targetLogs) || c.captureTarget(targetProfiles) {
g := new(errgroup.Group)
g.Go(c.captureInterval)
g.Go(c.captureLongRunning)
@ -264,11 +264,11 @@ func (c *cmd) prepare() (version string, err error) {
// If none are specified we will collect information from
// all by default
if len(c.capture) == 0 {
c.capture = c.defaultTargets()
c.capture = defaultTargets
}
for _, t := range c.capture {
if !c.allowedTarget(t) {
if !allowedTarget(t) {
return version, fmt.Errorf("target not found: %s", t)
}
}
@ -288,56 +288,48 @@ func (c *cmd) prepare() (version string, err error) {
// captureStatic captures static target information and writes it
// to the output path
func (c *cmd) captureStatic() error {
// Collect errors via multierror as we want to gracefully
// fail if an API is inaccessible
var errs error
// Collect the named outputs here
outputs := make(map[string]interface{})
// Capture host information
if c.configuredTarget("host") {
if c.captureTarget(targetHost) {
host, err := c.client.Agent().Host()
if err != nil {
errs = multierror.Append(errs, err)
}
outputs["host"] = host
if err := writeJSONFile(filepath.Join(c.output, targetHost+".json"), host); err != nil {
errs = multierror.Append(errs, err)
}
}
// Capture agent information
if c.configuredTarget("agent") {
if c.captureTarget(targetAgent) {
agent, err := c.client.Agent().Self()
if err != nil {
errs = multierror.Append(errs, err)
}
outputs["agent"] = agent
if err := writeJSONFile(filepath.Join(c.output, targetAgent+".json"), agent); err != nil {
errs = multierror.Append(errs, err)
}
}
// Capture cluster members information, including WAN
if c.configuredTarget("cluster") {
if c.captureTarget(targetMembers) {
members, err := c.client.Agent().Members(true)
if err != nil {
errs = multierror.Append(errs, err)
}
outputs["cluster"] = members
}
// Write all outputs to disk as JSON
for output, v := range outputs {
marshaled, err := json.MarshalIndent(v, "", "\t")
if err != nil {
errs = multierror.Append(errs, err)
}
err = ioutil.WriteFile(fmt.Sprintf("%s/%s.json", c.output, output), marshaled, 0644)
if err != nil {
if err := writeJSONFile(filepath.Join(c.output, targetMembers+".json"), members); err != nil {
errs = multierror.Append(errs, err)
}
}
return errs
}
func writeJSONFile(filename string, content interface{}) error {
marshaled, err := json.MarshalIndent(content, "", "\t")
if err != nil {
return err
}
return ioutil.WriteFile(filename, marshaled, 0644)
}
// captureInterval blocks for the duration of the command
// specified by the duration flag, capturing the dynamic
// targets at the interval specified
@ -380,7 +372,7 @@ func captureShortLived(c *cmd) error {
if err != nil {
return err
}
if c.configuredTarget("pprof") {
if c.captureTarget(targetProfiles) {
g.Go(func() error {
return c.captureHeap(timestampDir)
})
@ -417,7 +409,7 @@ func (c *cmd) captureLongRunning() error {
if s < 1 {
s = 1
}
if c.configuredTarget("pprof") {
if c.captureTarget(targetProfiles) {
g.Go(func() error {
return c.captureProfile(s, timestampDir)
})
@ -426,12 +418,12 @@ func (c *cmd) captureLongRunning() error {
return c.captureTrace(s, timestampDir)
})
}
if c.configuredTarget("logs") {
if c.captureTarget(targetLogs) {
g.Go(func() error {
return c.captureLogs(timestampDir)
})
}
if c.configuredTarget("metrics") {
if c.captureTarget(targetMetrics) {
// TODO: pass in context from caller
ctx, cancel := context.WithTimeout(context.Background(), c.duration)
defer cancel()
@ -450,8 +442,7 @@ func (c *cmd) captureGoRoutines(timestampDir string) error {
return fmt.Errorf("failed to collect goroutine profile: %w", err)
}
err = ioutil.WriteFile(fmt.Sprintf("%s/goroutine.prof", timestampDir), gr, 0644)
return err
return ioutil.WriteFile(fmt.Sprintf("%s/goroutine.prof", timestampDir), gr, 0644)
}
func (c *cmd) captureTrace(s float64, timestampDir string) error {
@ -460,8 +451,7 @@ func (c *cmd) captureTrace(s float64, timestampDir string) error {
return fmt.Errorf("failed to collect trace: %w", err)
}
err = ioutil.WriteFile(fmt.Sprintf("%s/trace.out", timestampDir), trace, 0644)
return err
return ioutil.WriteFile(fmt.Sprintf("%s/trace.out", timestampDir), trace, 0644)
}
func (c *cmd) captureProfile(s float64, timestampDir string) error {
@ -470,8 +460,7 @@ func (c *cmd) captureProfile(s float64, timestampDir string) error {
return fmt.Errorf("failed to collect cpu profile: %w", err)
}
err = ioutil.WriteFile(fmt.Sprintf("%s/profile.prof", timestampDir), prof, 0644)
return err
return ioutil.WriteFile(fmt.Sprintf("%s/profile.prof", timestampDir), prof, 0644)
}
func (c *cmd) captureHeap(timestampDir string) error {
@ -480,8 +469,7 @@ func (c *cmd) captureHeap(timestampDir string) error {
return fmt.Errorf("failed to collect heap profile: %w", err)
}
err = ioutil.WriteFile(fmt.Sprintf("%s/heap.prof", timestampDir), heap, 0644)
return err
return ioutil.WriteFile(fmt.Sprintf("%s/heap.prof", timestampDir), heap, 0644)
}
func (c *cmd) captureLogs(timestampDir string) error {
@ -538,23 +526,31 @@ func (c *cmd) captureMetrics(ctx context.Context, timestampDir string) error {
return nil
}
// allowedTarget returns a boolean if the target is able to be captured
func (c *cmd) allowedTarget(target string) bool {
for _, dt := range c.defaultTargets() {
// allowedTarget returns true if the target is a recognized name of a capture
// target.
func allowedTarget(target string) bool {
for _, dt := range defaultTargets {
if dt == target {
return true
}
}
for _, t := range deprecatedTargets {
if t == target {
return true
}
}
return false
}
// configuredTarget returns a boolean if the target is configured to be
// captured in the command
func (c *cmd) configuredTarget(target string) bool {
// captureTarget returns true if the target capture type is enabled.
func (c *cmd) captureTarget(target string) bool {
for _, dt := range c.capture {
if dt == target {
return true
}
if target == targetMembers && dt == targetCluster {
return true
}
}
return false
}
@ -676,12 +672,29 @@ func (c *cmd) createArchiveTemp(path string) (tempName string, err error) {
return tempName, nil
}
// defaultTargets specifies the list of all targets that
// will be captured by default
func (c *cmd) defaultTargets() []string {
return []string{"metrics", "logs", "pprof", "host", "agent", "cluster"}
const (
targetMetrics = "metrics"
targetLogs = "logs"
targetProfiles = "pprof"
targetHost = "host"
targetAgent = "agent"
targetMembers = "members"
// targetCluster is the now deprecated name for targetMembers
targetCluster = "cluster"
)
// defaultTargets specifies the list of targets that will be captured by default
var defaultTargets = []string{
targetMetrics,
targetLogs,
targetProfiles,
targetHost,
targetAgent,
targetMembers,
}
var deprecatedTargets = []string{targetCluster}
func (c *cmd) Synopsis() string {
return "Records a debugging archive for operators"
}

View File

@ -258,17 +258,17 @@ func TestDebugCommand_CaptureTargets(t *testing.T) {
"single": {
[]string{"agent"},
[]string{"agent.json"},
[]string{"host.json", "cluster.json"},
[]string{"host.json", "members.json"},
},
"static": {
[]string{"agent", "host", "cluster"},
[]string{"agent.json", "host.json", "cluster.json"},
[]string{"agent.json", "host.json", "members.json"},
[]string{"*/metrics.json"},
},
"metrics-only": {
[]string{"metrics"},
[]string{"*/metrics.json"},
[]string{"agent.json", "host.json", "cluster.json"},
[]string{"agent.json", "host.json", "members.json"},
},
"all-but-pprof": {
[]string{
@ -281,7 +281,7 @@ func TestDebugCommand_CaptureTargets(t *testing.T) {
[]string{
"host.json",
"agent.json",
"cluster.json",
"members.json",
"*/metrics.json",
"*/consul.log",
},