~sinzui/ubuntu/vivid/juju-core/vivid-1.24.6

« back to all changes in this revision

Viewing changes to src/gopkg.in/juju/charm.v5/metrics.go

  • Committer: Curtis Hovey
  • Date: 2015-09-30 14:14:54 UTC
  • mfrom: (1.1.34)
  • Revision ID: curtis@hovey.name-20150930141454-o3ldf23dzyjio6c0
Backport of 1.24.6 from wily. (LP: #1500916)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Canonical Ltd.
 
2
// Licensed under the LGPLv3, see LICENCE file for details.
 
3
 
 
4
package charm
 
5
 
 
6
import (
 
7
        "fmt"
 
8
        "io"
 
9
        "io/ioutil"
 
10
        "strconv"
 
11
 
 
12
        goyaml "gopkg.in/yaml.v1"
 
13
)
 
14
 
 
15
// MetricType is used to identify metric types supported by juju.
 
16
type MetricType string
 
17
 
 
18
const (
 
19
        // Supported metric types.
 
20
        MetricTypeGauge    MetricType = "gauge"
 
21
        MetricTypeAbsolute MetricType = "absolute"
 
22
)
 
23
 
 
24
// validateValue checks if the supplied metric value fits the requirements
 
25
// of its expected type.
 
26
func (m MetricType) validateValue(value string) error {
 
27
        switch m {
 
28
        case MetricTypeGauge, MetricTypeAbsolute:
 
29
                // The largest number of digits that can be returned by strconv.FormatFloat is 24, so
 
30
                // choose an arbitrary limit somewhat higher than that.
 
31
                if len(value) > 30 {
 
32
                        return fmt.Errorf("metric value is too large")
 
33
                }
 
34
                _, err := strconv.ParseFloat(value, 64)
 
35
                if err != nil {
 
36
                        return fmt.Errorf("invalid value type: expected float, got %q", value)
 
37
                }
 
38
        default:
 
39
                return fmt.Errorf("unknown metric type %q", m)
 
40
        }
 
41
        return nil
 
42
}
 
43
 
 
44
// Metric represents a single metric definition
 
45
type Metric struct {
 
46
        Type        MetricType
 
47
        Description string
 
48
}
 
49
 
 
50
// Metrics contains the metrics declarations encoded in the metrics.yaml
 
51
// file.
 
52
type Metrics struct {
 
53
        Metrics map[string]Metric
 
54
}
 
55
 
 
56
// ReadMetrics reads a MetricsDeclaration in YAML format.
 
57
func ReadMetrics(r io.Reader) (*Metrics, error) {
 
58
        data, err := ioutil.ReadAll(r)
 
59
        if err != nil {
 
60
                return nil, err
 
61
        }
 
62
        var metrics Metrics
 
63
        if err := goyaml.Unmarshal(data, &metrics); err != nil {
 
64
                return nil, err
 
65
        }
 
66
        if metrics.Metrics == nil {
 
67
                return &metrics, nil
 
68
        }
 
69
        for name, metric := range metrics.Metrics {
 
70
                switch metric.Type {
 
71
                case MetricTypeGauge, MetricTypeAbsolute:
 
72
                default:
 
73
                        return nil, fmt.Errorf("invalid metrics declaration: metric %q has unknown type %q", name, metric.Type)
 
74
                }
 
75
                if metric.Description == "" {
 
76
                        return nil, fmt.Errorf("invalid metrics declaration: metric %q lacks description", name)
 
77
                }
 
78
        }
 
79
        return &metrics, nil
 
80
}
 
81
 
 
82
// ValidateMetric validates the supplied metric name and value against the loaded
 
83
// metric definitions.
 
84
func (m Metrics) ValidateMetric(name, value string) error {
 
85
        metric, exists := m.Metrics[name]
 
86
        if !exists {
 
87
                return fmt.Errorf("metric %q not defined", name)
 
88
        }
 
89
        return metric.Type.validateValue(value)
 
90
}