...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package metric
16
17 import (
18 "sync"
19 "time"
20
21 "go.opencensus.io/internal/tagencoding"
22
23 "go.opencensus.io/metric/metricdata"
24 )
25
26
27
28
29
30
31
32
33 type baseMetric struct {
34 vals sync.Map
35 desc metricdata.Descriptor
36 start time.Time
37 keys []metricdata.LabelKey
38 constLabelValues []metricdata.LabelValue
39 bmType baseMetricType
40 }
41
42 type baseMetricType int
43
44 const (
45 gaugeInt64 baseMetricType = iota
46 gaugeFloat64
47 derivedGaugeInt64
48 derivedGaugeFloat64
49 cumulativeInt64
50 cumulativeFloat64
51 derivedCumulativeInt64
52 derivedCumulativeFloat64
53 )
54
55 type baseEntry interface {
56 read(t time.Time) metricdata.Point
57 }
58
59 func (bm *baseMetric) startTime() *time.Time {
60 switch bm.bmType {
61 case cumulativeInt64, cumulativeFloat64, derivedCumulativeInt64, derivedCumulativeFloat64:
62 return &bm.start
63 default:
64
65 return nil
66 }
67 }
68
69
70 func (bm *baseMetric) read() *metricdata.Metric {
71 now := time.Now()
72 startTime := bm.startTime()
73 if startTime == nil {
74 startTime = &now
75 }
76 m := &metricdata.Metric{
77 Descriptor: bm.desc,
78 }
79 bm.vals.Range(func(k, v interface{}) bool {
80 entry := v.(baseEntry)
81 key := k.(string)
82 labelVals := bm.decodeLabelVals(key)
83 m.TimeSeries = append(m.TimeSeries, &metricdata.TimeSeries{
84 StartTime: *startTime,
85 LabelValues: labelVals,
86 Points: []metricdata.Point{
87 entry.read(now),
88 },
89 })
90 return true
91 })
92 return m
93 }
94
95 func (bm *baseMetric) encodeLabelVals(labelVals []metricdata.LabelValue) string {
96 vb := &tagencoding.Values{}
97 for _, v := range labelVals {
98 b := make([]byte, 1, len(v.Value)+1)
99 if v.Present {
100 b[0] = 1
101 b = append(b, []byte(v.Value)...)
102 }
103 vb.WriteValue(b)
104 }
105 return string(vb.Bytes())
106 }
107
108 func (bm *baseMetric) decodeLabelVals(s string) []metricdata.LabelValue {
109 vals := make([]metricdata.LabelValue, 0, len(bm.keys))
110 vb := &tagencoding.Values{Buffer: []byte(s)}
111 for range bm.keys {
112 v := vb.ReadValue()
113 if v[0] == 0 {
114 vals = append(vals, metricdata.LabelValue{})
115 } else {
116 vals = append(vals, metricdata.NewLabelValue(string(v[1:])))
117 }
118 }
119 return vals
120 }
121
122 func (bm *baseMetric) entryForValues(labelVals []metricdata.LabelValue, newEntry func() baseEntry) (interface{}, error) {
123 labelVals = append(bm.constLabelValues, labelVals...)
124 if len(labelVals) != len(bm.keys) {
125 return nil, errKeyValueMismatch
126 }
127 mapKey := bm.encodeLabelVals(labelVals)
128 if entry, ok := bm.vals.Load(mapKey); ok {
129 return entry, nil
130 }
131 entry, _ := bm.vals.LoadOrStore(mapKey, newEntry())
132 return entry, nil
133 }
134
135 func (bm *baseMetric) upsertEntry(labelVals []metricdata.LabelValue, newEntry func() baseEntry) error {
136 labelVals = append(bm.constLabelValues, labelVals...)
137 if len(labelVals) != len(bm.keys) {
138 return errKeyValueMismatch
139 }
140 mapKey := bm.encodeLabelVals(labelVals)
141 bm.vals.Delete(mapKey)
142 bm.vals.Store(mapKey, newEntry())
143 return nil
144 }
145
View as plain text