github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/metricsdebug/metricsdebug.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package metricsdebug
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"strings"
    10  	"text/tabwriter"
    11  	"time"
    12  
    13  	"github.com/juju/cmd"
    14  	"github.com/juju/errors"
    15  	"github.com/juju/names"
    16  	"launchpad.net/gnuflag"
    17  
    18  	"github.com/juju/juju/api/metricsdebug"
    19  	"github.com/juju/juju/apiserver/params"
    20  	"github.com/juju/juju/cmd/modelcmd"
    21  )
    22  
    23  const debugMetricsDoc = `
    24  debug-metrics
    25  display recently collected metrics and exit
    26  `
    27  
    28  // DebugMetricsCommand retrieves metrics stored in the juju controller.
    29  type DebugMetricsCommand struct {
    30  	modelcmd.ModelCommandBase
    31  	Json  bool
    32  	Tag   names.Tag
    33  	Count int
    34  }
    35  
    36  // New creates a new DebugMetricsCommand.
    37  func New() cmd.Command {
    38  	return modelcmd.Wrap(&DebugMetricsCommand{})
    39  }
    40  
    41  // Info implements Command.Info.
    42  func (c *DebugMetricsCommand) Info() *cmd.Info {
    43  	return &cmd.Info{
    44  		Name:    "debug-metrics",
    45  		Args:    "[service or unit]",
    46  		Purpose: "retrieve metrics collected by the given unit/service",
    47  		Doc:     debugMetricsDoc,
    48  	}
    49  }
    50  
    51  // Init reads and verifies the cli arguments for the DebugMetricsCommand
    52  func (c *DebugMetricsCommand) Init(args []string) error {
    53  	if len(args) == 0 {
    54  		return errors.New("you need to specify a unit or service.")
    55  	}
    56  	if names.IsValidUnit(args[0]) {
    57  		c.Tag = names.NewUnitTag(args[0])
    58  	} else if names.IsValidService(args[0]) {
    59  		c.Tag = names.NewServiceTag(args[0])
    60  	} else {
    61  		return errors.Errorf("%q is not a valid unit or service", args[0])
    62  	}
    63  	if err := cmd.CheckEmpty(args[1:]); err != nil {
    64  		return errors.Errorf("unknown command line arguments: " + strings.Join(args, ","))
    65  	}
    66  	return nil
    67  }
    68  
    69  // SetFlags implements Command.SetFlags.
    70  func (c *DebugMetricsCommand) SetFlags(f *gnuflag.FlagSet) {
    71  	c.ModelCommandBase.SetFlags(f)
    72  	f.IntVar(&c.Count, "n", 0, "number of metrics to retrieve")
    73  	f.BoolVar(&c.Json, "json", false, "output metrics as json")
    74  }
    75  
    76  type GetMetricsClient interface {
    77  	GetMetrics(tag string) ([]params.MetricResult, error)
    78  	Close() error
    79  }
    80  
    81  var newClient = func(env modelcmd.ModelCommandBase) (GetMetricsClient, error) {
    82  	state, err := env.NewAPIRoot()
    83  	if err != nil {
    84  		return nil, errors.Trace(err)
    85  	}
    86  	return metricsdebug.NewClient(state), nil
    87  }
    88  
    89  // Run implements Command.Run.
    90  func (c *DebugMetricsCommand) Run(ctx *cmd.Context) error {
    91  	client, err := newClient(c.ModelCommandBase)
    92  	if err != nil {
    93  		return errors.Trace(err)
    94  	}
    95  	metrics, err := client.GetMetrics(c.Tag.String())
    96  	if err != nil {
    97  		return errors.Trace(err)
    98  	}
    99  	defer client.Close()
   100  	if len(metrics) == 0 {
   101  		return nil
   102  	}
   103  	if c.Count > 0 && len(metrics) > c.Count {
   104  		metrics = metrics[:c.Count]
   105  	}
   106  	if c.Json {
   107  		b, err := json.MarshalIndent(metrics, "", "    ")
   108  		if err != nil {
   109  			return errors.Trace(err)
   110  		}
   111  		fmt.Fprintf(ctx.Stdout, string(b))
   112  		return nil
   113  	}
   114  	tw := tabwriter.NewWriter(ctx.Stdout, 0, 1, 1, ' ', 0)
   115  	fmt.Fprintf(tw, "TIME\tMETRIC\tVALUE\n")
   116  	for _, m := range metrics {
   117  		fmt.Fprintf(tw, "%v\t%v\t%v\n", m.Time.Format(time.RFC3339), m.Key, m.Value)
   118  	}
   119  	tw.Flush()
   120  	return nil
   121  }