instrument.go 10 KB

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