// Copyright The OpenTelemetry Authors // // 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. // Example using the OTLP exporter + collector + third-party backends. For // information about using the exporter, see: // https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp?tab=doc#example-package-Insecure package main import ( "context" "fmt" "log" "time" "google.golang.org/grpc" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp" "go.opentelemetry.io/otel/exporters/otlp/otlpgrpc" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/global" "go.opentelemetry.io/otel/propagation" controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" "go.opentelemetry.io/otel/sdk/metric/selector/simple" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/semconv" "go.opentelemetry.io/otel/trace" ) // Initializes an OTLP exporter, and configures the corresponding trace and // metric providers. func initProvider() func() { ctx := context.Background() // If the OpenTelemetry Collector is running on a local cluster (minikube or // microk8s), it should be accessible through the NodePort service at the // `localhost:30080` endpoint. Otherwise, replace `localhost` with the // endpoint of your cluster. If you run the app inside k8s, then you can // probably connect directly to the service through dns driver := otlpgrpc.NewDriver( otlpgrpc.WithInsecure(), otlpgrpc.WithEndpoint("localhost:30080"), otlpgrpc.WithDialOption(grpc.WithBlock()), // useful for testing ) exp, err := otlp.NewExporter(ctx, driver) handleErr(err, "failed to create exporter") res, err := resource.New(ctx, resource.WithAttributes( // the service name used to display traces in backends semconv.ServiceNameKey.String("test-service"), ), ) handleErr(err, "failed to create resource") bsp := sdktrace.NewBatchSpanProcessor(exp) tracerProvider := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithResource(res), sdktrace.WithSpanProcessor(bsp), ) cont := controller.New( processor.New( simple.NewWithExactDistribution(), exp, ), controller.WithExporter(exp), controller.WithCollectPeriod(2*time.Second), ) // set global propagator to tracecontext (the default is no-op). otel.SetTextMapPropagator(propagation.TraceContext{}) otel.SetTracerProvider(tracerProvider) global.SetMeterProvider(cont.MeterProvider()) handleErr(cont.Start(context.Background()), "failed to start controller") return func() { // Push any last metric events to the exporter. handleErr(cont.Stop(context.Background()), "failed to stop controller") // Shutdown will flush any remaining spans and shut down the exporter. handleErr(tracerProvider.Shutdown(ctx), "failed to shutdown TracerProvider") } } func main() { log.Printf("Waiting for connection...") shutdown := initProvider() defer shutdown() tracer := otel.Tracer("test-tracer") meter := global.Meter("test-meter") // labels represent additional key-value descriptors that can be bound to a // metric observer or recorder. commonLabels := []attribute.KeyValue{ attribute.String("labelA", "chocolate"), attribute.String("labelB", "raspberry"), attribute.String("labelC", "vanilla"), } // Recorder metric example valuerecorder := metric.Must(meter). NewFloat64Counter( "an_important_metric", metric.WithDescription("Measures the cumulative epicness of the app"), ).Bind(commonLabels...) defer valuerecorder.Unbind() // work begins ctx, span := tracer.Start( context.Background(), "CollectorExporter-Example", trace.WithAttributes(commonLabels...)) defer span.End() for i := 0; i < 10; i++ { _, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i)) log.Printf("Doing really hard work (%d / 10)\n", i+1) valuerecorder.Add(ctx, 1.0) <-time.After(time.Second) iSpan.End() } log.Printf("Done!") } func handleErr(err error, message string) { if err != nil { log.Fatalf("%s: %v", message, err) } }