Skip to content

Instantly share code, notes, and snippets.

@gbbr
Last active June 4, 2024 02:08
Show Gist options
  • Save gbbr/4a54dd02d34ad05e694952e0a02e1c67 to your computer and use it in GitHub Desktop.
Save gbbr/4a54dd02d34ad05e694952e0a02e1c67 to your computer and use it in GitHub Desktop.
Connecting to OTLP endpoints with Datadog
// 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 OTLP exporters + 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"
"flag"
"fmt"
"log"
"time"
"google.golang.org/grpc"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"go.opentelemetry.io/otel/trace"
)
var httpDriver = flag.Bool("http", false, "use HTTP exporter instead of gRPC")
func init() {
flag.Parse()
}
// Initializes an OTLP exporter, and configures the corresponding trace and
// metric providers.
func initProvider() func() {
ctx := context.Background()
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")
// 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
// Set up a trace exporter
var traceExporter sdktrace.SpanExporter
if *httpDriver {
endpoint := "localhost:50051"
log.Printf("Sending to gRPC endpoint: %s.\n", endpoint)
traceExporter, err = otlptracehttp.New(ctx,
otlptracehttp.WithInsecure(),
otlptracehttp.WithEndpoint(endpoint),
)
} else {
endpoint := "localhost:4317"
log.Printf("Sending to gRPC endpoint: %s.\n", endpoint)
traceExporter, err = otlptracegrpc.New(ctx,
otlptracegrpc.WithInsecure(),
otlptracegrpc.WithEndpoint(endpoint),
otlptracegrpc.WithDialOption(grpc.WithBlock()),
)
}
handleErr(err, "failed to create trace exporter")
// Register the trace exporter with a TracerProvider, using a batch
// span processor to aggregate spans before export.
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
// set global propagator to tracecontext (the default is no-op).
otel.SetTextMapPropagator(propagation.TraceContext{})
return func() {
// 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")
// 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"),
attribute.Float64("_sampling_priority_v1", 2),
}
// 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)
<-time.After(time.Second)
iSpan.End()
}
log.Printf("Done!")
}
func handleErr(err error, message string) {
if err != nil {
log.Fatalf("%s: %v", message, err)
}
}
@duxing
Copy link

duxing commented Apr 20, 2022

hi @gbbr ! Thanks for making this example!

according to L54, it seems like the value of service.name will be used as the "APM service name" on Datadog backend, which functions the same as DD_SERVICE in dd-trace or opentelemetry-exporter-datadog.

I was wondering if you have a map for how to set trace data attributes for other Datadog APM data.

e.g. DD_ENV in the past would be used for APM service environment but with OTLP implementation, I'm not 100% sure if deployment.environment is the right attribute for that.

Thanks in advance!

@gbbr
Copy link
Author

gbbr commented Apr 20, 2022

Hi there 👋 !

deployment.environment should be picked up correctly, and so should env. We are in the process of writing this documentation and something should be released soon :)

@gbbr
Copy link
Author

gbbr commented Apr 20, 2022

We're probably going to have to ask for more details, so I think it's best you reach out to support, as that channel is more suited for better communication, rather than a gist here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment