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 }