1 // Copyright 2019, 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 // Float64Cumulative represents a float64 value that can only go up. 26 // 27 // Float64Cumulative maintains a float64 value for each combination of label values 28 // passed to the Set or Inc methods. 29 type Float64Cumulative struct { 30 bm baseMetric 31 } 32 33 // Float64CumulativeEntry represents a single value of the cumulative corresponding to a set 34 // of label values. 35 type Float64CumulativeEntry struct { 36 val uint64 // needs to be uint64 for atomic access, interpret with math.Float64frombits 37 } 38 39 func (e *Float64CumulativeEntry) 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 cumulative entry where each key for this cumulative 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 cumulative was created. 52 func (c *Float64Cumulative) GetEntry(labelVals ...metricdata.LabelValue) (*Float64CumulativeEntry, error) { 53 entry, err := c.bm.entryForValues(labelVals, func() baseEntry { 54 return &Float64CumulativeEntry{} 55 }) 56 if err != nil { 57 return nil, err 58 } 59 return entry.(*Float64CumulativeEntry), nil 60 } 61 62 // Inc increments the cumulative entry value by val. It returns without incrementing if the val 63 // is negative. 64 func (e *Float64CumulativeEntry) Inc(val float64) { 65 var swapped bool 66 if val <= 0.0 { 67 return 68 } 69 for !swapped { 70 oldVal := atomic.LoadUint64(&e.val) 71 newVal := math.Float64bits(math.Float64frombits(oldVal) + val) 72 swapped = atomic.CompareAndSwapUint64(&e.val, oldVal, newVal) 73 } 74 } 75 76 // Int64Cumulative represents a int64 cumulative value that can only go up. 77 // 78 // Int64Cumulative maintains an int64 value for each combination of label values passed to the 79 // Set or Inc methods. 80 type Int64Cumulative struct { 81 bm baseMetric 82 } 83 84 // Int64CumulativeEntry represents a single value of the cumulative corresponding to a set 85 // of label values. 86 type Int64CumulativeEntry struct { 87 val int64 88 } 89 90 func (e *Int64CumulativeEntry) read(t time.Time) metricdata.Point { 91 v := atomic.LoadInt64(&e.val) 92 if v < 0 { 93 v = 0.0 94 } 95 return metricdata.NewInt64Point(t, v) 96 } 97 98 // GetEntry returns a cumulative entry where each key for this cumulative has the value 99 // given. 100 // 101 // The number of label values supplied must be exactly the same as the number 102 // of keys supplied when this cumulative was created. 103 func (c *Int64Cumulative) GetEntry(labelVals ...metricdata.LabelValue) (*Int64CumulativeEntry, error) { 104 entry, err := c.bm.entryForValues(labelVals, func() baseEntry { 105 return &Int64CumulativeEntry{} 106 }) 107 if err != nil { 108 return nil, err 109 } 110 return entry.(*Int64CumulativeEntry), nil 111 } 112 113 // Inc increments the current cumulative entry value by val. It returns without incrementing if 114 // the val is negative. 115 func (e *Int64CumulativeEntry) Inc(val int64) { 116 if val <= 0 { 117 return 118 } 119 atomic.AddInt64(&e.val, val) 120 } 121 122 // Int64DerivedCumulative represents int64 cumulative value that is derived from an object. 123 // 124 // Int64DerivedCumulative maintains objects for each combination of label values. 125 // These objects implement Int64DerivedCumulativeInterface to read instantaneous value 126 // representing the object. 127 type Int64DerivedCumulative struct { 128 bm baseMetric 129 } 130 131 type int64DerivedCumulativeEntry struct { 132 fn func() int64 133 } 134 135 func (e *int64DerivedCumulativeEntry) read(t time.Time) metricdata.Point { 136 // TODO: [rghetia] handle a condition where new value return by fn is lower than previous call. 137 // It requires that we maintain the old values. 138 return metricdata.NewInt64Point(t, e.fn()) 139 } 140 141 // UpsertEntry inserts or updates a derived cumulative entry for the given set of label values. 142 // The object for which this cumulative 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 cumulative was created. 147 // 2. fn func() int64 is nil. 148 func (c *Int64DerivedCumulative) UpsertEntry(fn func() int64, labelVals ...metricdata.LabelValue) error { 149 if fn == nil { 150 return errInvalidParam 151 } 152 return c.bm.upsertEntry(labelVals, func() baseEntry { 153 return &int64DerivedCumulativeEntry{fn} 154 }) 155 } 156 157 // Float64DerivedCumulative represents float64 cumulative value that is derived from an object. 158 // 159 // Float64DerivedCumulative maintains objects for each combination of label values. 160 // These objects implement Float64DerivedCumulativeInterface to read instantaneous value 161 // representing the object. 162 type Float64DerivedCumulative struct { 163 bm baseMetric 164 } 165 166 type float64DerivedCumulativeEntry struct { 167 fn func() float64 168 } 169 170 func (e *float64DerivedCumulativeEntry) read(t time.Time) metricdata.Point { 171 return metricdata.NewFloat64Point(t, e.fn()) 172 } 173 174 // UpsertEntry inserts or updates a derived cumulative entry for the given set of label values. 175 // The object for which this cumulative 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 cumulative was created. 180 // 2. fn func() float64 is nil. 181 func (c *Float64DerivedCumulative) UpsertEntry(fn func() float64, labelVals ...metricdata.LabelValue) error { 182 if fn == nil { 183 return errInvalidParam 184 } 185 return c.bm.upsertEntry(labelVals, func() baseEntry { 186 return &float64DerivedCumulativeEntry{fn} 187 }) 188 } 189