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

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // Package metricsmanager contains the implementation of an api endpoint
     5  // for calling metrics functions in state.
     6  package metricsmanager
     7  
     8  import (
     9  	"github.com/juju/errors"
    10  	"github.com/juju/loggo"
    11  	"github.com/juju/names"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/metricsender"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/state"
    17  )
    18  
    19  var (
    20  	logger            = loggo.GetLogger("juju.apiserver.metricsmanager")
    21  	maxBatchesPerSend = metricsender.DefaultMaxBatchesPerSend()
    22  
    23  	sender = metricsender.DefaultMetricSender()
    24  )
    25  
    26  func init() {
    27  	common.RegisterStandardFacade("MetricsManager", 1, NewMetricsManagerAPI)
    28  }
    29  
    30  // MetricsManager defines the methods on the metricsmanager API end point.
    31  type MetricsManager interface {
    32  	CleanupOldMetrics(arg params.Entities) (params.ErrorResults, error)
    33  	SendMetrics(args params.Entities) (params.ErrorResults, error)
    34  }
    35  
    36  // MetricsManagerAPI implements the metrics manager interface and is the concrete
    37  // implementation of the api end point.
    38  type MetricsManagerAPI struct {
    39  	state *state.State
    40  
    41  	accessEnviron common.GetAuthFunc
    42  }
    43  
    44  var _ MetricsManager = (*MetricsManagerAPI)(nil)
    45  
    46  // NewMetricsManagerAPI creates a new API endpoint for calling metrics manager functions.
    47  func NewMetricsManagerAPI(
    48  	st *state.State,
    49  	resources *common.Resources,
    50  	authorizer common.Authorizer,
    51  ) (*MetricsManagerAPI, error) {
    52  	if !(authorizer.AuthMachineAgent() && authorizer.AuthModelManager()) {
    53  		return nil, common.ErrPerm
    54  	}
    55  
    56  	// Allow access only to the current environment.
    57  	accessEnviron := func() (common.AuthFunc, error) {
    58  		return func(tag names.Tag) bool {
    59  			if tag == nil {
    60  				return false
    61  			}
    62  			return tag == st.ModelTag()
    63  		}, nil
    64  	}
    65  
    66  	return &MetricsManagerAPI{
    67  		state:         st,
    68  		accessEnviron: accessEnviron,
    69  	}, nil
    70  }
    71  
    72  // CleanupOldMetrics removes old metrics from the collection.
    73  // The single arg params is expected to contain and environment uuid.
    74  // Even though the call will delete all metrics across environments
    75  // it serves to validate that the connection has access to at least one environment.
    76  func (api *MetricsManagerAPI) CleanupOldMetrics(args params.Entities) (params.ErrorResults, error) {
    77  	result := params.ErrorResults{
    78  		Results: make([]params.ErrorResult, len(args.Entities)),
    79  	}
    80  	if len(args.Entities) == 0 {
    81  		return result, nil
    82  	}
    83  	canAccess, err := api.accessEnviron()
    84  	if err != nil {
    85  		return result, err
    86  	}
    87  	for i, arg := range args.Entities {
    88  		tag, err := names.ParseModelTag(arg.Tag)
    89  		if err != nil {
    90  			result.Results[i].Error = common.ServerError(common.ErrPerm)
    91  			continue
    92  		}
    93  		if !canAccess(tag) {
    94  			result.Results[i].Error = common.ServerError(common.ErrPerm)
    95  			continue
    96  		}
    97  		err = api.state.CleanupOldMetrics()
    98  		if err != nil {
    99  			err = errors.Annotate(err, "failed to cleanup old metrics")
   100  			result.Results[i].Error = common.ServerError(err)
   101  		}
   102  	}
   103  	return result, nil
   104  }
   105  
   106  // SendMetrics will send any unsent metrics onto the metric collection service.
   107  func (api *MetricsManagerAPI) SendMetrics(args params.Entities) (params.ErrorResults, error) {
   108  	result := params.ErrorResults{
   109  		Results: make([]params.ErrorResult, len(args.Entities)),
   110  	}
   111  	if len(args.Entities) == 0 {
   112  		return result, nil
   113  	}
   114  	canAccess, err := api.accessEnviron()
   115  	if err != nil {
   116  		return result, err
   117  	}
   118  	for i, arg := range args.Entities {
   119  		tag, err := names.ParseModelTag(arg.Tag)
   120  		if err != nil {
   121  			result.Results[i].Error = common.ServerError(err)
   122  			continue
   123  		}
   124  		if !canAccess(tag) {
   125  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   126  			continue
   127  		}
   128  		err = metricsender.SendMetrics(api.state, sender, maxBatchesPerSend)
   129  		if err != nil {
   130  			err = errors.Annotate(err, "failed to send metrics")
   131  			logger.Warningf("%v", err)
   132  			result.Results[i].Error = common.ServerError(err)
   133  			continue
   134  		}
   135  	}
   136  	return result, nil
   137  }