github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/runner/jujuc/add-metric.go (about)

     1  // Copyright 2012-2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/juju/cmd"
    12  	"github.com/juju/errors"
    13  	"github.com/juju/gnuflag"
    14  	"github.com/juju/utils/keyvalues"
    15  	"gopkg.in/juju/charm.v6"
    16  
    17  	jujucmd "github.com/juju/juju/cmd"
    18  )
    19  
    20  // Metric represents a single metric set by the charm.
    21  type Metric struct {
    22  	Key    string
    23  	Value  string
    24  	Time   time.Time
    25  	Labels map[string]string `json:",omitempty"`
    26  }
    27  
    28  // AddMetricCommand implements the add-metric command.
    29  type AddMetricCommand struct {
    30  	cmd.CommandBase
    31  	ctx     Context
    32  	Labels  string
    33  	Metrics []Metric
    34  }
    35  
    36  // NewAddMetricCommand generates a new AddMetricCommand.
    37  func NewAddMetricCommand(ctx Context) (cmd.Command, error) {
    38  	return &AddMetricCommand{ctx: ctx}, nil
    39  }
    40  
    41  // Info returns the command info structure for the add-metric command.
    42  func (c *AddMetricCommand) Info() *cmd.Info {
    43  	return jujucmd.Info(&cmd.Info{
    44  		Name:    "add-metric",
    45  		Args:    "key1=value1 [key2=value2 ...]",
    46  		Purpose: "add metrics",
    47  	})
    48  }
    49  
    50  // SetFlags implements Command.
    51  func (c *AddMetricCommand) SetFlags(f *gnuflag.FlagSet) {
    52  	f.StringVar(&c.Labels, "l", "", "labels to be associated with metric values")
    53  	f.StringVar(&c.Labels, "labels", "", "")
    54  }
    55  
    56  // Init parses the command's parameters.
    57  func (c *AddMetricCommand) Init(args []string) error {
    58  	// TODO(fwereade): 2016-03-17 lp:1558657
    59  	now := time.Now()
    60  	if len(args) == 0 {
    61  		return fmt.Errorf("no metrics specified")
    62  	}
    63  	kvs, err := keyvalues.Parse(args, false)
    64  	if err != nil {
    65  		return errors.Annotate(err, "invalid metrics")
    66  	}
    67  	var labelArgs []string
    68  	if c.Labels != "" {
    69  		labelArgs = strings.Split(c.Labels, ",")
    70  	}
    71  	for key, value := range kvs {
    72  		labels, err := keyvalues.Parse(labelArgs, false)
    73  		if err != nil {
    74  			return errors.Annotate(err, "invalid labels")
    75  		}
    76  		c.Metrics = append(c.Metrics, Metric{
    77  			Key:    key,
    78  			Value:  value,
    79  			Time:   now,
    80  			Labels: labels,
    81  		})
    82  	}
    83  	return nil
    84  }
    85  
    86  // Run adds metrics to the hook context.
    87  func (c *AddMetricCommand) Run(ctx *cmd.Context) (err error) {
    88  	for _, metric := range c.Metrics {
    89  		if charm.IsBuiltinMetric(metric.Key) {
    90  			return errors.Errorf("%v uses a reserved prefix", metric.Key)
    91  		}
    92  		if len(metric.Labels) > 0 {
    93  			err := c.ctx.AddMetricLabels(metric.Key, metric.Value, metric.Time, metric.Labels)
    94  			if err != nil {
    95  				return errors.Annotate(err, "cannot record metric")
    96  			}
    97  		} else {
    98  			err := c.ctx.AddMetric(metric.Key, metric.Value, metric.Time)
    99  			if err != nil {
   100  				return errors.Annotate(err, "cannot record metric")
   101  			}
   102  		}
   103  	}
   104  	return nil
   105  }