instrument.go 10 KB

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