1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
4
// Package metricsdebug contains the implementation of an api endpoint
5
// for metrics debug functionality.
9
"github.com/juju/errors"
10
"gopkg.in/juju/names.v2"
12
"github.com/juju/juju/apiserver/common"
13
"github.com/juju/juju/apiserver/facade"
14
"github.com/juju/juju/apiserver/params"
15
"github.com/juju/juju/state"
19
common.RegisterStandardFacade("MetricsDebug", 2, NewMetricsDebugAPI)
22
type metricsDebug interface {
23
// MetricBatchesForUnit returns metric batches for the given unit.
24
MetricBatchesForUnit(unit string) ([]state.MetricBatch, error)
26
// MetricBatchesForService returns metric batches for the given service.
27
MetricBatchesForService(service string) ([]state.MetricBatch, error)
29
// Unit returns the unit based on its name.
30
Unit(string) (*state.Unit, error)
32
// Application returns the application based on its name.
33
Application(string) (*state.Application, error)
36
// MetricsDebug defines the methods on the metricsdebug API end point.
37
type MetricsDebug interface {
38
// GetMetrics returns all metrics stored by the state server.
39
GetMetrics(arg params.Entities) (params.MetricResults, error)
41
// SetMeterStatus will set the meter status on the given entity tag.
42
SetMeterStatus(params.MeterStatusParams) (params.ErrorResults, error)
45
// MetricsDebugAPI implements the metricsdebug interface and is the concrete
46
// implementation of the api end point.
47
type MetricsDebugAPI struct {
51
var _ MetricsDebug = (*MetricsDebugAPI)(nil)
53
// NewMetricsDebugAPI creates a new API endpoint for calling metrics debug functions.
54
func NewMetricsDebugAPI(
56
resources facade.Resources,
57
authorizer facade.Authorizer,
58
) (*MetricsDebugAPI, error) {
59
if !authorizer.AuthClient() {
60
return nil, common.ErrPerm
63
return &MetricsDebugAPI{
68
// GetMetrics returns all metrics stored by the state server.
69
func (api *MetricsDebugAPI) GetMetrics(args params.Entities) (params.MetricResults, error) {
70
results := params.MetricResults{
71
Results: make([]params.EntityMetrics, len(args.Entities)),
73
if len(args.Entities) == 0 {
76
for i, arg := range args.Entities {
77
tag, err := names.ParseTag(arg.Tag)
79
results.Results[i].Error = common.ServerError(err)
82
var batches []state.MetricBatch
84
case names.UnitTagKind:
85
batches, err = api.state.MetricBatchesForUnit(tag.Id())
87
err = errors.Annotate(err, "failed to get metrics")
88
results.Results[i].Error = common.ServerError(err)
91
case names.ApplicationTagKind:
92
batches, err = api.state.MetricBatchesForService(tag.Id())
94
err = errors.Annotate(err, "failed to get metrics")
95
results.Results[i].Error = common.ServerError(err)
99
err := errors.Errorf("invalid tag %v", arg.Tag)
100
results.Results[i].Error = common.ServerError(err)
103
for _, b := range batches {
104
metricCount += len(b.Metrics())
106
metrics := make([]params.MetricResult, metricCount)
108
for _, mb := range batches {
109
for _, m := range mb.Metrics() {
110
metrics[ix] = params.MetricResult{
117
results.Results[i].Metrics = metrics
123
// SetMeterStatus sets meter statuses for entities.
124
func (api *MetricsDebugAPI) SetMeterStatus(args params.MeterStatusParams) (params.ErrorResults, error) {
125
results := params.ErrorResults{
126
Results: make([]params.ErrorResult, len(args.Statuses)),
128
for i, arg := range args.Statuses {
129
tag, err := names.ParseTag(arg.Tag)
131
results.Results[i].Error = common.ServerError(err)
134
err = api.setEntityMeterStatus(tag, state.MeterStatus{
135
Code: state.MeterStatusFromString(arg.Code),
139
results.Results[i].Error = common.ServerError(err)
146
func (api *MetricsDebugAPI) setEntityMeterStatus(entity names.Tag, status state.MeterStatus) error {
147
switch entity := entity.(type) {
149
unit, err := api.state.Unit(entity.Id())
151
return errors.Trace(err)
153
chURL, found := unit.CharmURL()
155
return errors.New("no charm url")
157
if chURL.Schema != "local" {
158
return errors.New("not a local charm")
160
err = unit.SetMeterStatus(status.Code.String(), status.Info)
162
return errors.Trace(err)
164
case names.ApplicationTag:
165
service, err := api.state.Application(entity.Id())
167
return errors.Trace(err)
169
chURL, _ := service.CharmURL()
170
if chURL.Schema != "local" {
171
return errors.New("not a local charm")
173
units, err := service.AllUnits()
175
return errors.Trace(err)
177
for _, unit := range units {
178
err := unit.SetMeterStatus(status.Code.String(), status.Info)
180
return errors.Trace(err)
184
return errors.Errorf("expected application or unit tag, got %T", entity)