So the OpenTelemetry Go API is finally reaching stability. Using it:
module example.com/app
require (
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/metric v1.16.0
)
And in the application:
1package main
2
3import (
4 "context"
5 "sync/atomic"
6
7 "go.opentelemetry.io/otel"
8 "go.opentelemetry.io/otel/attribute"
9 "go.opentelemetry.io/otel/metric"
10)
11
12func main() {
13 // get the global meterprovider and create a meter named for our application
14 meter := otel.Meter("example.com/app")
15
16 // create a counter
17 c1, err := meter.Int64Counter("counter1",
18 // a string description
19 metric.WithDescription("represents a thing"),
20 // units, UCUM "c/s" type
21 // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/README.md#instrument-units
22 // https://unitsofmeasure.org/ucum#section-Alphabetic-Index-By-Symbol
23 metric.WithUnit("s"),
24 )
25 if err != nil {
26 panic(err)
27 }
28
29 // context, future possibility of extracting exemplars
30 ctx := context.Background()
31
32 c1.Add(ctx, 1, metric.WithAttributes(
33 // additional attributes for this datapoint
34 attribute.String("foo", "bar"),
35 ))
36
37 // fake a synchronous gauge by using an atomic counter
38 // this way we can set the value when we have one
39 g := new(atomic.Int64)
40 g.Store(22)
41 // create a gauge
42 _, err = meter.Int64ObservableGauge("gauge1",
43 // a string description
44 metric.WithDescription("represents another thing"),
45 // async requires a callback to observe the value
46 metric.WithInt64Callback(func(ctx context.Context, io metric.Int64Observer) error {
47 io.Observe(g.Load(), metric.WithAttributes(
48 attribute.String("fizz", "buzz"),
49 ))
50 return nil
51 }),
52 )
53 if err != nil {
54 panic(err)
55 }
56}