example/metric/collector/example.go (122 lines of code) (raw):

// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "log" "math/rand" "sync" "time" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" sdkmetric "go.opentelemetry.io/otel/sdk/metric" ) type observedFloat struct { mu sync.RWMutex f float64 } func (of *observedFloat) set(v float64) { of.mu.Lock() defer of.mu.Unlock() of.f = v } func (of *observedFloat) get() float64 { of.mu.RLock() defer of.mu.RUnlock() return of.f } func newObservedFloat(v float64) *observedFloat { return &observedFloat{ f: v, } } type observedInt struct { mu sync.RWMutex i int64 } func (oi *observedInt) set(v int64) { oi.mu.Lock() defer oi.mu.Unlock() oi.i = v } func (oi *observedInt) get() int64 { oi.mu.RLock() defer oi.mu.RUnlock() return oi.i } func newObservedInt(v int64) *observedInt { return &observedInt{ i: v, } } // Export OTLP metrtics using the otlpmetrichttp exporter. // This example is used to demostrate how to use the collector approach to export metrics to Google Cloud. func main() { ctx := context.Background() exp, err := otlpmetrichttp.New(ctx, otlpmetrichttp.WithInsecure()) if err != nil { panic(err) } // initialize a MeterProvider with that periodically exports to the otlp exporter. provider := sdkmetric.NewMeterProvider( sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exp)), ) defer func() { if err = provider.Shutdown(ctx); err != nil { log.Fatalf("failed to shutdown meter provider: %v", err) } }() // Create a meter with which we will record metrics for our package. meter := provider.Meter("github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/collector/metric") // Register counter value counter, err := meter.Int64Counter("counter-a-collector") if err != nil { log.Fatalf("Failed to create counter: %v", err) } clabels := []attribute.KeyValue{attribute.Key("key").String("value")} counter.Add(ctx, 100, metric.WithAttributes(clabels...)) histogram, err := meter.Float64Histogram("histogram-b-collector") if err != nil { log.Fatalf("Failed to create histogram: %v", err) } // Register observer value olabels := []attribute.KeyValue{ attribute.String("foo", "Tokyo"), attribute.String("bar", "Sushi"), } of := newObservedFloat(12.34) gaugeObserver, err := meter.Float64ObservableGauge("observer-a-collector") if err != nil { log.Fatalf("failed to initialize instrument: %v", err) } _, err = meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { v := of.get() o.ObserveFloat64(gaugeObserver, v, metric.WithAttributes(olabels...)) return nil }, gaugeObserver) if err != nil { log.Fatalf("failed to register callback: %v", err) } oi := newObservedInt(3) // Export boolean as a custom type (Boolean types are not supported in OTLP) gaugeObserverBool, err := meter.Int64ObservableGauge("observer-boolean-collector", metric.WithUnit("{gcp.BOOL}")) if err != nil { log.Fatalf("failed to initialize instrument: %v", err) } _, err = meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { v := oi.get() o.ObserveInt64(gaugeObserverBool, v, metric.WithAttributes(clabels...)) return nil }, gaugeObserverBool) if err != nil { log.Fatalf("failed to register callback: %v", err) } // Add measurement once an every 10 second. timer := time.NewTicker(10 * time.Second) rng := rand.New(rand.NewSource(time.Now().UnixNano())) for range timer.C { r := rng.Int63n(100) cv := 100 + r counter.Add(ctx, cv, metric.WithAttributes(clabels...)) r2 := rng.Int63n(100) hv := float64(r2) / 20.0 histogram.Record(ctx, hv, metric.WithAttributes(clabels...)) ovf := 12.34 + hv of.set(ovf) r3 := rng.Int63n(2) // 0 or 1 ovi := int64(r3) oi.set(ovi) log.Printf("Most recent data: counter %v, observer-float %v; observer-int %v; histogram %v", cv, ovf, ovi, hv) } }