instrument.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Copyright The OpenTelemetry 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. package metric // import "go.opentelemetry.io/otel/metric"
  15. import "go.opentelemetry.io/otel/attribute"
  16. // Observable is used as a grouping mechanism for all instruments that are
  17. // updated within a Callback.
  18. type Observable interface {
  19. observable()
  20. }
  21. // InstrumentOption applies options to all instruments.
  22. type InstrumentOption interface {
  23. Int64CounterOption
  24. Int64UpDownCounterOption
  25. Int64HistogramOption
  26. Int64ObservableCounterOption
  27. Int64ObservableUpDownCounterOption
  28. Int64ObservableGaugeOption
  29. Float64CounterOption
  30. Float64UpDownCounterOption
  31. Float64HistogramOption
  32. Float64ObservableCounterOption
  33. Float64ObservableUpDownCounterOption
  34. Float64ObservableGaugeOption
  35. }
  36. // HistogramOption applies options to histogram instruments.
  37. type HistogramOption interface {
  38. Int64HistogramOption
  39. Float64HistogramOption
  40. }
  41. type descOpt string
  42. func (o descOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
  43. c.description = string(o)
  44. return c
  45. }
  46. func (o descOpt) applyFloat64UpDownCounter(c Float64UpDownCounterConfig) Float64UpDownCounterConfig {
  47. c.description = string(o)
  48. return c
  49. }
  50. func (o descOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
  51. c.description = string(o)
  52. return c
  53. }
  54. func (o descOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
  55. c.description = string(o)
  56. return c
  57. }
  58. func (o descOpt) applyFloat64ObservableUpDownCounter(c Float64ObservableUpDownCounterConfig) Float64ObservableUpDownCounterConfig {
  59. c.description = string(o)
  60. return c
  61. }
  62. func (o descOpt) applyFloat64ObservableGauge(c Float64ObservableGaugeConfig) Float64ObservableGaugeConfig {
  63. c.description = string(o)
  64. return c
  65. }
  66. func (o descOpt) applyInt64Counter(c Int64CounterConfig) Int64CounterConfig {
  67. c.description = string(o)
  68. return c
  69. }
  70. func (o descOpt) applyInt64UpDownCounter(c Int64UpDownCounterConfig) Int64UpDownCounterConfig {
  71. c.description = string(o)
  72. return c
  73. }
  74. func (o descOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
  75. c.description = string(o)
  76. return c
  77. }
  78. func (o descOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
  79. c.description = string(o)
  80. return c
  81. }
  82. func (o descOpt) applyInt64ObservableUpDownCounter(c Int64ObservableUpDownCounterConfig) Int64ObservableUpDownCounterConfig {
  83. c.description = string(o)
  84. return c
  85. }
  86. func (o descOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64ObservableGaugeConfig {
  87. c.description = string(o)
  88. return c
  89. }
  90. // WithDescription sets the instrument description.
  91. func WithDescription(desc string) InstrumentOption { return descOpt(desc) }
  92. type unitOpt string
  93. func (o unitOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
  94. c.unit = string(o)
  95. return c
  96. }
  97. func (o unitOpt) applyFloat64UpDownCounter(c Float64UpDownCounterConfig) Float64UpDownCounterConfig {
  98. c.unit = string(o)
  99. return c
  100. }
  101. func (o unitOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
  102. c.unit = string(o)
  103. return c
  104. }
  105. func (o unitOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
  106. c.unit = string(o)
  107. return c
  108. }
  109. func (o unitOpt) applyFloat64ObservableUpDownCounter(c Float64ObservableUpDownCounterConfig) Float64ObservableUpDownCounterConfig {
  110. c.unit = string(o)
  111. return c
  112. }
  113. func (o unitOpt) applyFloat64ObservableGauge(c Float64ObservableGaugeConfig) Float64ObservableGaugeConfig {
  114. c.unit = string(o)
  115. return c
  116. }
  117. func (o unitOpt) applyInt64Counter(c Int64CounterConfig) Int64CounterConfig {
  118. c.unit = string(o)
  119. return c
  120. }
  121. func (o unitOpt) applyInt64UpDownCounter(c Int64UpDownCounterConfig) Int64UpDownCounterConfig {
  122. c.unit = string(o)
  123. return c
  124. }
  125. func (o unitOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
  126. c.unit = string(o)
  127. return c
  128. }
  129. func (o unitOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
  130. c.unit = string(o)
  131. return c
  132. }
  133. func (o unitOpt) applyInt64ObservableUpDownCounter(c Int64ObservableUpDownCounterConfig) Int64ObservableUpDownCounterConfig {
  134. c.unit = string(o)
  135. return c
  136. }
  137. func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64ObservableGaugeConfig {
  138. c.unit = string(o)
  139. return c
  140. }
  141. // WithUnit sets the instrument unit.
  142. //
  143. // The unit u should be defined using the appropriate [UCUM](https://ucum.org) case-sensitive code.
  144. func WithUnit(u string) InstrumentOption { return unitOpt(u) }
  145. // WithExplicitBucketBoundaries sets the instrument explicit bucket boundaries.
  146. //
  147. // This option is considered "advisory", and may be ignored by API implementations.
  148. func WithExplicitBucketBoundaries(bounds ...float64) HistogramOption { return bucketOpt(bounds) }
  149. type bucketOpt []float64
  150. func (o bucketOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
  151. c.explicitBucketBoundaries = o
  152. return c
  153. }
  154. func (o bucketOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
  155. c.explicitBucketBoundaries = o
  156. return c
  157. }
  158. // AddOption applies options to an addition measurement. See
  159. // [MeasurementOption] for other options that can be used as an AddOption.
  160. type AddOption interface {
  161. applyAdd(AddConfig) AddConfig
  162. }
  163. // AddConfig contains options for an addition measurement.
  164. type AddConfig struct {
  165. attrs attribute.Set
  166. }
  167. // NewAddConfig returns a new [AddConfig] with all opts applied.
  168. func NewAddConfig(opts []AddOption) AddConfig {
  169. config := AddConfig{attrs: *attribute.EmptySet()}
  170. for _, o := range opts {
  171. config = o.applyAdd(config)
  172. }
  173. return config
  174. }
  175. // Attributes returns the configured attribute set.
  176. func (c AddConfig) Attributes() attribute.Set {
  177. return c.attrs
  178. }
  179. // RecordOption applies options to an addition measurement. See
  180. // [MeasurementOption] for other options that can be used as a RecordOption.
  181. type RecordOption interface {
  182. applyRecord(RecordConfig) RecordConfig
  183. }
  184. // RecordConfig contains options for a recorded measurement.
  185. type RecordConfig struct {
  186. attrs attribute.Set
  187. }
  188. // NewRecordConfig returns a new [RecordConfig] with all opts applied.
  189. func NewRecordConfig(opts []RecordOption) RecordConfig {
  190. config := RecordConfig{attrs: *attribute.EmptySet()}
  191. for _, o := range opts {
  192. config = o.applyRecord(config)
  193. }
  194. return config
  195. }
  196. // Attributes returns the configured attribute set.
  197. func (c RecordConfig) Attributes() attribute.Set {
  198. return c.attrs
  199. }
  200. // ObserveOption applies options to an addition measurement. See
  201. // [MeasurementOption] for other options that can be used as a ObserveOption.
  202. type ObserveOption interface {
  203. applyObserve(ObserveConfig) ObserveConfig
  204. }
  205. // ObserveConfig contains options for an observed measurement.
  206. type ObserveConfig struct {
  207. attrs attribute.Set
  208. }
  209. // NewObserveConfig returns a new [ObserveConfig] with all opts applied.
  210. func NewObserveConfig(opts []ObserveOption) ObserveConfig {
  211. config := ObserveConfig{attrs: *attribute.EmptySet()}
  212. for _, o := range opts {
  213. config = o.applyObserve(config)
  214. }
  215. return config
  216. }
  217. // Attributes returns the configured attribute set.
  218. func (c ObserveConfig) Attributes() attribute.Set {
  219. return c.attrs
  220. }
  221. // MeasurementOption applies options to all instrument measurement.
  222. type MeasurementOption interface {
  223. AddOption
  224. RecordOption
  225. ObserveOption
  226. }
  227. type attrOpt struct {
  228. set attribute.Set
  229. }
  230. // mergeSets returns the union of keys between a and b. Any duplicate keys will
  231. // use the value associated with b.
  232. func mergeSets(a, b attribute.Set) attribute.Set {
  233. // NewMergeIterator uses the first value for any duplicates.
  234. iter := attribute.NewMergeIterator(&b, &a)
  235. merged := make([]attribute.KeyValue, 0, a.Len()+b.Len())
  236. for iter.Next() {
  237. merged = append(merged, iter.Attribute())
  238. }
  239. return attribute.NewSet(merged...)
  240. }
  241. func (o attrOpt) applyAdd(c AddConfig) AddConfig {
  242. switch {
  243. case o.set.Len() == 0:
  244. case c.attrs.Len() == 0:
  245. c.attrs = o.set
  246. default:
  247. c.attrs = mergeSets(c.attrs, o.set)
  248. }
  249. return c
  250. }
  251. func (o attrOpt) applyRecord(c RecordConfig) RecordConfig {
  252. switch {
  253. case o.set.Len() == 0:
  254. case c.attrs.Len() == 0:
  255. c.attrs = o.set
  256. default:
  257. c.attrs = mergeSets(c.attrs, o.set)
  258. }
  259. return c
  260. }
  261. func (o attrOpt) applyObserve(c ObserveConfig) ObserveConfig {
  262. switch {
  263. case o.set.Len() == 0:
  264. case c.attrs.Len() == 0:
  265. c.attrs = o.set
  266. default:
  267. c.attrs = mergeSets(c.attrs, o.set)
  268. }
  269. return c
  270. }
  271. // WithAttributeSet sets the attribute Set associated with a measurement is
  272. // made with.
  273. //
  274. // If multiple WithAttributeSet or WithAttributes options are passed the
  275. // attributes will be merged together in the order they are passed. Attributes
  276. // with duplicate keys will use the last value passed.
  277. func WithAttributeSet(attributes attribute.Set) MeasurementOption {
  278. return attrOpt{set: attributes}
  279. }
  280. // WithAttributes converts attributes into an attribute Set and sets the Set to
  281. // be associated with a measurement. This is shorthand for:
  282. //
  283. // cp := make([]attribute.KeyValue, len(attributes))
  284. // copy(cp, attributes)
  285. // WithAttributes(attribute.NewSet(cp...))
  286. //
  287. // [attribute.NewSet] may modify the passed attributes so this will make a copy
  288. // of attributes before creating a set in order to ensure this function is
  289. // concurrent safe. This makes this option function less optimized in
  290. // comparison to [WithAttributeSet]. Therefore, [WithAttributeSet] should be
  291. // preferred for performance sensitive code.
  292. //
  293. // See [WithAttributeSet] for information about how multiple WithAttributes are
  294. // merged.
  295. func WithAttributes(attributes ...attribute.KeyValue) MeasurementOption {
  296. cp := make([]attribute.KeyValue, len(attributes))
  297. copy(cp, attributes)
  298. return attrOpt{set: attribute.NewSet(cp...)}
  299. }