1 // Copyright 2018, OpenCensus Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package metric 16 17 import ( 18 "math" 19 "sync/atomic" 20 "time" 21 22 "go.opencensus.io/metric/metricdata" 23 ) 24 25 // Float64Gauge represents a float64 value that can go up and down. 26 // 27 // Float64Gauge maintains a float64 value for each combination of of label values 28 // passed to the Set or Add methods. 29 type Float64Gauge struct { 30 bm baseMetric 31 } 32 33 // Float64Entry represents a single value of the gauge corresponding to a set 34 // of label values. 35 type Float64Entry struct { 36 val uint64 // needs to be uint64 for atomic access, interpret with math.Float64frombits 37 } 38 39 func (e *Float64Entry) read(t time.Time) metricdata.Point { 40 v := math.Float64frombits(atomic.LoadUint64(&e.val)) 41 if v < 0 { 42 v = 0 43 } 44 return metricdata.NewFloat64Point(t, v) 45 } 46 47 // GetEntry returns a gauge entry where each key for this gauge has the value 48 // given. 49 // 50 // The number of label values supplied must be exactly the same as the number 51 // of keys supplied when this gauge was created. 52 func (g *Float64Gauge) GetEntry(labelVals ...metricdata.LabelValue) (*Float64Entry, error) { 53 entry, err := g.bm.entryForValues(labelVals, func() baseEntry { 54 return &Float64Entry{} 55 }) 56 if err != nil { 57 return nil, err 58 } 59 return entry.(*Float64Entry), nil 60 } 61 62 // Set sets the gauge entry value to val. 63 func (e *Float64Entry) Set(val float64) { 64 atomic.StoreUint64(&e.val, math.Float64bits(val)) 65 } 66 67 // Add increments the gauge entry value by val. 68 func (e *Float64Entry) Add(val float64) { 69 var swapped bool 70 for !swapped { 71 oldVal := atomic.LoadUint64(&e.val) 72 newVal := math.Float64bits(math.Float64frombits(oldVal) + val) 73 swapped = atomic.CompareAndSwapUint64(&e.val, oldVal, newVal) 74 } 75 } 76 77 // Int64Gauge represents a int64 gauge value that can go up and down. 78 // 79 // Int64Gauge maintains an int64 value for each combination of label values passed to the 80 // Set or Add methods. 81 type Int64Gauge struct { 82 bm baseMetric 83 } 84 85 // Int64GaugeEntry represents a single value of the gauge corresponding to a set 86 // of label values. 87 type Int64GaugeEntry struct { 88 val int64 89 } 90 91 func (e *Int64GaugeEntry) read(t time.Time) metricdata.Point { 92 v := atomic.LoadInt64(&e.val) 93 if v < 0 { 94 v = 0.0 95 } 96 return metricdata.NewInt64Point(t, v) 97 } 98 99 // GetEntry returns a gauge entry where each key for this gauge has the value 100 // given. 101 // 102 // The number of label values supplied must be exactly the same as the number 103 // of keys supplied when this gauge was created. 104 func (g *Int64Gauge) GetEntry(labelVals ...metricdata.LabelValue) (*Int64GaugeEntry, error) { 105 entry, err := g.bm.entryForValues(labelVals, func() baseEntry { 106 return &Int64GaugeEntry{} 107 }) 108 if err != nil { 109 return nil, err 110 } 111 return entry.(*Int64GaugeEntry), nil 112 } 113 114 // Set sets the value of the gauge entry to the provided value. 115 func (e *Int64GaugeEntry) Set(val int64) { 116 atomic.StoreInt64(&e.val, val) 117 } 118 119 // Add increments the current gauge entry value by val, which may be negative. 120 func (e *Int64GaugeEntry) Add(val int64) { 121 atomic.AddInt64(&e.val, val) 122 } 123 124 // Int64DerivedGauge represents int64 gauge value that is derived from an object. 125 // 126 // Int64DerivedGauge maintains objects for each combination of label values. 127 // These objects implement Int64DerivedGaugeInterface to read instantaneous value 128 // representing the object. 129 type Int64DerivedGauge struct { 130 bm baseMetric 131 } 132 133 type int64DerivedGaugeEntry struct { 134 fn func() int64 135 } 136 137 func (e *int64DerivedGaugeEntry) read(t time.Time) metricdata.Point { 138 return metricdata.NewInt64Point(t, e.fn()) 139 } 140 141 // UpsertEntry inserts or updates a derived gauge entry for the given set of label values. 142 // The object for which this gauge entry is inserted or updated, must implement func() int64 143 // 144 // It returns an error if 145 // 1. The number of label values supplied are not the same as the number 146 // of keys supplied when this gauge was created. 147 // 2. fn func() int64 is nil. 148 func (g *Int64DerivedGauge) UpsertEntry(fn func() int64, labelVals ...metricdata.LabelValue) error { 149 if fn == nil { 150 return errInvalidParam 151 } 152 return g.bm.upsertEntry(labelVals, func() baseEntry { 153 return &int64DerivedGaugeEntry{fn} 154 }) 155 } 156 157 // Float64DerivedGauge represents float64 gauge value that is derived from an object. 158 // 159 // Float64DerivedGauge maintains objects for each combination of label values. 160 // These objects implement Float64DerivedGaugeInterface to read instantaneous value 161 // representing the object. 162 type Float64DerivedGauge struct { 163 bm baseMetric 164 } 165 166 type float64DerivedGaugeEntry struct { 167 fn func() float64 168 } 169 170 func (e *float64DerivedGaugeEntry) read(t time.Time) metricdata.Point { 171 return metricdata.NewFloat64Point(t, e.fn()) 172 } 173 174 // UpsertEntry inserts or updates a derived gauge entry for the given set of label values. 175 // The object for which this gauge entry is inserted or updated, must implement func() float64 176 // 177 // It returns an error if 178 // 1. The number of label values supplied are not the same as the number 179 // of keys supplied when this gauge was created. 180 // 2. fn func() float64 is nil. 181 func (g *Float64DerivedGauge) UpsertEntry(fn func() float64, labelVals ...metricdata.LabelValue) error { 182 if fn == nil { 183 return errInvalidParam 184 } 185 return g.bm.upsertEntry(labelVals, func() baseEntry { 186 return &float64DerivedGaugeEntry{fn} 187 }) 188 } 189