| Abhay Kumar | 40252eb | 2025-10-13 13:25:53 +0000 | [diff] [blame^] | 1 | // Copyright The OpenTelemetry Authors |
| 2 | // SPDX-License-Identifier: Apache-2.0 |
| 3 | |
| 4 | /* |
| 5 | Package metric provides the OpenTelemetry API used to measure metrics about |
| 6 | source code operation. |
| 7 | |
| 8 | This API is separate from its implementation so the instrumentation built from |
| 9 | it is reusable. See [go.opentelemetry.io/otel/sdk/metric] for the official |
| 10 | OpenTelemetry implementation of this API. |
| 11 | |
| 12 | All measurements made with this package are made via instruments. These |
| 13 | instruments are created by a [Meter] which itself is created by a |
| 14 | [MeterProvider]. Applications need to accept a [MeterProvider] implementation |
| 15 | as a starting point when instrumenting. This can be done directly, or by using |
| 16 | the OpenTelemetry global MeterProvider via [GetMeterProvider]. Using an |
| 17 | appropriately named [Meter] from the accepted [MeterProvider], instrumentation |
| 18 | can then be built from the [Meter]'s instruments. |
| 19 | |
| 20 | # Instruments |
| 21 | |
| 22 | Each instrument is designed to make measurements of a particular type. Broadly, |
| 23 | all instruments fall into two overlapping logical categories: asynchronous or |
| 24 | synchronous, and int64 or float64. |
| 25 | |
| 26 | All synchronous instruments ([Int64Counter], [Int64UpDownCounter], |
| 27 | [Int64Histogram], [Float64Counter], [Float64UpDownCounter], and |
| 28 | [Float64Histogram]) are used to measure the operation and performance of source |
| 29 | code during the source code execution. These instruments only make measurements |
| 30 | when the source code they instrument is run. |
| 31 | |
| 32 | All asynchronous instruments ([Int64ObservableCounter], |
| 33 | [Int64ObservableUpDownCounter], [Int64ObservableGauge], |
| 34 | [Float64ObservableCounter], [Float64ObservableUpDownCounter], and |
| 35 | [Float64ObservableGauge]) are used to measure metrics outside of the execution |
| 36 | of source code. They are said to make "observations" via a callback function |
| 37 | called once every measurement collection cycle. |
| 38 | |
| 39 | Each instrument is also grouped by the value type it measures. Either int64 or |
| 40 | float64. The value being measured will dictate which instrument in these |
| 41 | categories to use. |
| 42 | |
| 43 | Outside of these two broad categories, instruments are described by the |
| 44 | function they are designed to serve. All Counters ([Int64Counter], |
| 45 | [Float64Counter], [Int64ObservableCounter], and [Float64ObservableCounter]) are |
| 46 | designed to measure values that never decrease in value, but instead only |
| 47 | incrementally increase in value. UpDownCounters ([Int64UpDownCounter], |
| 48 | [Float64UpDownCounter], [Int64ObservableUpDownCounter], and |
| 49 | [Float64ObservableUpDownCounter]) on the other hand, are designed to measure |
| 50 | values that can increase and decrease. When more information needs to be |
| 51 | conveyed about all the synchronous measurements made during a collection cycle, |
| 52 | a Histogram ([Int64Histogram] and [Float64Histogram]) should be used. Finally, |
| 53 | when just the most recent measurement needs to be conveyed about an |
| 54 | asynchronous measurement, a Gauge ([Int64ObservableGauge] and |
| 55 | [Float64ObservableGauge]) should be used. |
| 56 | |
| 57 | See the [OpenTelemetry documentation] for more information about instruments |
| 58 | and their intended use. |
| 59 | |
| 60 | # Instrument Name |
| 61 | |
| 62 | OpenTelemetry defines an [instrument name syntax] that restricts what |
| 63 | instrument names are allowed. |
| 64 | |
| 65 | Instrument names should ... |
| 66 | |
| 67 | - Not be empty. |
| 68 | - Have an alphabetic character as their first letter. |
| 69 | - Have any letter after the first be an alphanumeric character, ‘_’, ‘.’, |
| 70 | ‘-’, or ‘/’. |
| 71 | - Have a maximum length of 255 letters. |
| 72 | |
| 73 | To ensure compatibility with observability platforms, all instruments created |
| 74 | need to conform to this syntax. Not all implementations of the API will validate |
| 75 | these names, it is the callers responsibility to ensure compliance. |
| 76 | |
| 77 | # Measurements |
| 78 | |
| 79 | Measurements are made by recording values and information about the values with |
| 80 | an instrument. How these measurements are recorded depends on the instrument. |
| 81 | |
| 82 | Measurements for synchronous instruments ([Int64Counter], [Int64UpDownCounter], |
| 83 | [Int64Histogram], [Float64Counter], [Float64UpDownCounter], and |
| 84 | [Float64Histogram]) are recorded using the instrument methods directly. All |
| 85 | counter instruments have an Add method that is used to measure an increment |
| 86 | value, and all histogram instruments have a Record method to measure a data |
| 87 | point. |
| 88 | |
| 89 | Asynchronous instruments ([Int64ObservableCounter], |
| 90 | [Int64ObservableUpDownCounter], [Int64ObservableGauge], |
| 91 | [Float64ObservableCounter], [Float64ObservableUpDownCounter], and |
| 92 | [Float64ObservableGauge]) record measurements within a callback function. The |
| 93 | callback is registered with the Meter which ensures the callback is called once |
| 94 | per collection cycle. A callback can be registered two ways: during the |
| 95 | instrument's creation using an option, or later using the RegisterCallback |
| 96 | method of the [Meter] that created the instrument. |
| 97 | |
| 98 | If the following criteria are met, an option ([WithInt64Callback] or |
| 99 | [WithFloat64Callback]) can be used during the asynchronous instrument's |
| 100 | creation to register a callback ([Int64Callback] or [Float64Callback], |
| 101 | respectively): |
| 102 | |
| 103 | - The measurement process is known when the instrument is created |
| 104 | - Only that instrument will make a measurement within the callback |
| 105 | - The callback never needs to be unregistered |
| 106 | |
| 107 | If the criteria are not met, use the RegisterCallback method of the [Meter] that |
| 108 | created the instrument to register a [Callback]. |
| 109 | |
| 110 | # API Implementations |
| 111 | |
| 112 | This package does not conform to the standard Go versioning policy, all of its |
| 113 | interfaces may have methods added to them without a package major version bump. |
| 114 | This non-standard API evolution could surprise an uninformed implementation |
| 115 | author. They could unknowingly build their implementation in a way that would |
| 116 | result in a runtime panic for their users that update to the new API. |
| 117 | |
| 118 | The API is designed to help inform an instrumentation author about this |
| 119 | non-standard API evolution. It requires them to choose a default behavior for |
| 120 | unimplemented interface methods. There are three behavior choices they can |
| 121 | make: |
| 122 | |
| 123 | - Compilation failure |
| 124 | - Panic |
| 125 | - Default to another implementation |
| 126 | |
| 127 | All interfaces in this API embed a corresponding interface from |
| 128 | [go.opentelemetry.io/otel/metric/embedded]. If an author wants the default |
| 129 | behavior of their implementations to be a compilation failure, signaling to |
| 130 | their users they need to update to the latest version of that implementation, |
| 131 | they need to embed the corresponding interface from |
| 132 | [go.opentelemetry.io/otel/metric/embedded] in their implementation. For |
| 133 | example, |
| 134 | |
| 135 | import "go.opentelemetry.io/otel/metric/embedded" |
| 136 | |
| 137 | type MeterProvider struct { |
| 138 | embedded.MeterProvider |
| 139 | // ... |
| 140 | } |
| 141 | |
| 142 | If an author wants the default behavior of their implementations to a panic, |
| 143 | they need to embed the API interface directly. |
| 144 | |
| 145 | import "go.opentelemetry.io/otel/metric" |
| 146 | |
| 147 | type MeterProvider struct { |
| 148 | metric.MeterProvider |
| 149 | // ... |
| 150 | } |
| 151 | |
| 152 | This is not a recommended behavior as it could lead to publishing packages that |
| 153 | contain runtime panics when users update other package that use newer versions |
| 154 | of [go.opentelemetry.io/otel/metric]. |
| 155 | |
| 156 | Finally, an author can embed another implementation in theirs. The embedded |
| 157 | implementation will be used for methods not defined by the author. For example, |
| 158 | an author who wants to default to silently dropping the call can use |
| 159 | [go.opentelemetry.io/otel/metric/noop]: |
| 160 | |
| 161 | import "go.opentelemetry.io/otel/metric/noop" |
| 162 | |
| 163 | type MeterProvider struct { |
| 164 | noop.MeterProvider |
| 165 | // ... |
| 166 | } |
| 167 | |
| 168 | It is strongly recommended that authors only embed |
| 169 | [go.opentelemetry.io/otel/metric/noop] if they choose this default behavior. |
| 170 | That implementation is the only one OpenTelemetry authors can guarantee will |
| 171 | fully implement all the API interfaces when a user updates their API. |
| 172 | |
| 173 | [instrument name syntax]: https://opentelemetry.io/docs/specs/otel/metrics/api/#instrument-name-syntax |
| 174 | [OpenTelemetry documentation]: https://opentelemetry.io/docs/concepts/signals/metrics/ |
| 175 | [GetMeterProvider]: https://pkg.go.dev/go.opentelemetry.io/otel#GetMeterProvider |
| 176 | */ |
| 177 | package metric // import "go.opentelemetry.io/otel/metric" |