1 // Copyright 2017, 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 16 package stats 17 18 import ( 19 "sync" 20 "sync/atomic" 21 ) 22 23 // Measure represents a single numeric value to be tracked and recorded. 24 // For example, latency, request bytes, and response bytes could be measures 25 // to collect from a server. 26 // 27 // Measures by themselves have no outside effects. In order to be exported, 28 // the measure needs to be used in a View. If no Views are defined over a 29 // measure, there is very little cost in recording it. 30 type Measure interface { 31 // Name returns the name of this measure. 32 // 33 // Measure names are globally unique (among all libraries linked into your program). 34 // We recommend prefixing the measure name with a domain name relevant to your 35 // project or application. 36 // 37 // Measure names are never sent over the wire or exported to backends. 38 // They are only used to create Views. 39 Name() string 40 41 // Description returns the human-readable description of this measure. 42 Description() string 43 44 // Unit returns the units for the values this measure takes on. 45 // 46 // Units are encoded according to the case-sensitive abbreviations from the 47 // Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html 48 Unit() string 49 } 50 51 // measureDescriptor is the untyped descriptor associated with each measure. 52 // Int64Measure and Float64Measure wrap measureDescriptor to provide typed 53 // recording APIs. 54 // Two Measures with the same name will have the same measureDescriptor. 55 type measureDescriptor struct { 56 subs int32 // access atomically 57 58 name string 59 description string 60 unit string 61 } 62 63 func (m *measureDescriptor) subscribe() { 64 atomic.StoreInt32(&m.subs, 1) 65 } 66 67 func (m *measureDescriptor) subscribed() bool { 68 return atomic.LoadInt32(&m.subs) == 1 69 } 70 71 var ( 72 mu sync.RWMutex 73 measures = make(map[string]*measureDescriptor) 74 ) 75 76 func registerMeasureHandle(name, desc, unit string) *measureDescriptor { 77 mu.Lock() 78 defer mu.Unlock() 79 80 if stored, ok := measures[name]; ok { 81 return stored 82 } 83 m := &measureDescriptor{ 84 name: name, 85 description: desc, 86 unit: unit, 87 } 88 measures[name] = m 89 return m 90 } 91 92 // Measurement is the numeric value measured when recording stats. Each measure 93 // provides methods to create measurements of their kind. For example, Int64Measure 94 // provides M to convert an int64 into a measurement. 95 type Measurement struct { 96 v float64 97 m Measure 98 desc *measureDescriptor 99 } 100 101 // Value returns the value of the Measurement as a float64. 102 func (m Measurement) Value() float64 { 103 return m.v 104 } 105 106 // Measure returns the Measure from which this Measurement was created. 107 func (m Measurement) Measure() Measure { 108 return m.m 109 } 110