oteldatadogtie

package module
v0.0.0-...-e7bd787 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2024 License: MIT Imports: 12 Imported by: 0

README

oteldatadogtie

A wrapper for integrating Open Telemetry traces with datadog continuous profiling tool.

Install

go get github.com/GuanceCloud/oteldatadogtie

Example

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/GuanceCloud/oteldatadogtie"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	"go.opentelemetry.io/otel/trace"
	"gopkg.in/DataDog/dd-trace-go.v1/profiler"
)

var OtelTracer trace.Tracer

func httpExporter(ctx context.Context) (sdktrace.SpanExporter, error) {
	exporter, err := otlptracehttp.New(ctx,
		otlptracehttp.WithEndpoint("127.0.0.1:9529"),
		otlptracehttp.WithURLPath("/otel/v1/trace"),
		otlptracehttp.WithInsecure(),
		otlptracehttp.WithCompression(otlptracehttp.GzipCompression),
		otlptracehttp.WithTimeout(time.Second*15),
		otlptracehttp.WithRetry(otlptracehttp.RetryConfig{
			Enabled:         true,
			InitialInterval: time.Second,
			MaxInterval:     time.Second * 15,
			MaxElapsedTime:  time.Minute * 2,
		}),
	)

	return exporter, err
}

func stdoutExporter(_ context.Context) (sdktrace.SpanExporter, error) {
	return stdouttrace.New(stdouttrace.WithPrettyPrint())
}

func main() {
	ctx := context.Background()

	exporter, err := httpExporter(ctx)
	if err != nil {
		log.Fatalf("unable to init exporter: %v", err)
	}

	tp := oteldatadogtie.NewTracerProvider(
		sdktrace.WithBatcher(exporter,
			sdktrace.WithBatchTimeout(time.Second),
			sdktrace.WithExportTimeout(time.Second*15),
		),
	)

	defer tp.Shutdown(ctx)

	otel.SetTracerProvider(tp)

	// If you need to use custom Resource, you should add attribute 
	// oteldatadogtie.AttributeRuntimeID to it, then you can call the 
	// Open Telemetry original sdktrace.NewTracerProvider function as usual, 
	// at last use oteldatadogtie.Wrap function to wrap your TracerProvider 
	// instance, for example:
	//
	// res, err := resource.New(ctx,
	// 	resource.WithProcess(),
	// 	resource.WithAttributes(
	// 		attribute.String("foo", "bar"),
	// 		oteldatadogtie.AttributeRuntimeID,
	// 	),
	// )
	// if err != nil {
	// 	log.Fatalf("unable to build resource: %v", err)
	// }
	// if res, err = resource.Merge(resource.Default(), res); err != nil {
	// 	log.Fatalf("unable to merge resource: %v", err)
	// }
	//
	// tp2 := sdktrace.NewTracerProvider(
	// 	sdktrace.WithBatcher(
	// 		exporter,
	// 		sdktrace.WithBatchTimeout(time.Second),
	// 		sdktrace.WithExportTimeout(time.Second*15),
	// 	),
	// 	sdktrace.WithResource(res),
	// )
	//
	// defer tp2.Shutdown(ctx)
	// otel.SetTracerProvider(oteldatadogtie.Wrap(tp2))

	OtelTracer = otel.Tracer("oteldatadogtie")

	// Use our oteldatadogtie.Start wrapper to start Datadog profiler,
	// or use the original Datadog profiler.Start and combine setting
	// tag oteldatadogtie.TagRuntimeID, see oteldatadogtie.StartDDProfiler
	// for details.
	err = oteldatadogtie.StartDDProfiler(
		profiler.WithProfileTypes(profiler.CPUProfile, profiler.HeapProfile, profiler.MutexProfile, profiler.GoroutineProfile),
		profiler.WithService("oteldatadogtie-demo"),
		profiler.WithEnv("testing"),
		profiler.WithVersion("v0.0.1"),
		profiler.WithAgentAddr("127.0.0.1:9529"),
	)
	if err != nil {
		log.Fatalf("unable to start dd profiler: %v", err)
	}

	defer oteldatadogtie.StopDDProfiler()

	n := 27

	for {
		func() {
			newCtx, span := OtelTracer.Start(ctx, "main", trace.WithAttributes(attribute.Int("n", n)))
			defer span.End()
			fmt.Printf("fibonacci(%d) = %d\n", n, fibonacci(newCtx, n))
			time.Sleep(time.Second * 5)
		}()
	}
}

func fibonacci(ctx context.Context, n int) int {
	newCtx := ctx
	if n%6 == 5 {
		var span trace.Span
		newCtx, span = OtelTracer.Start(ctx, "fibonacci", trace.WithAttributes(attribute.Int("n", n)))
		defer span.End()
	}

	if n < 2 {
		return 1
	}

	return fibonacci(newCtx, n-1) + fibonacci(newCtx, n-2)
}

Documentation

Index

Constants

View Source
const (
	SpanID          = "span id"
	LocalRootSpanID = "local root span id"
	TraceEndpoint   = "trace endpoint"
)

These constants are copied from https://github.com/DataDog/dd-trace-go/blob/main/internal/traceprof/traceprof.go

View Source
const KeyRuntimeID attribute.Key = ext.RuntimeID

KeyRuntimeID is used to mark a process uniquely

Variables

View Source
var AttributeRuntimeID = KeyRuntimeID.String(runtimeID)
View Source
var StopDDProfiler = profiler.Stop
View Source
var (
	TagRuntimeID = ext.RuntimeID + ":" + runtimeID
)

Functions

func RuntimeID

func RuntimeID() string

func StartDDProfiler

func StartDDProfiler(opts ...profiler.Option) error

StartDDProfiler is a wrapper of Datadog profiler.Start function, the purpose is simply to set the tag runtime-id to our custom value, you can also use the original Datadog profiler.Start function (if required) and combining setting the TagRuntimeID tag.

Types

type TracerProviderWrapper

type TracerProviderWrapper struct {
	*sdktrace.TracerProvider
}

func NewTracerProvider

func NewTracerProvider(opts ...sdktrace.TracerProviderOption) *TracerProviderWrapper

NewTracerProvider is a wrapper of trace.NewTracerProvider function in Open Telemetry trace sdk, it adds AttributeRuntimeID attribute to Resource config and then call Wrap function, if you need to config you custom Resource, you can use the original otel trace.NewTracerProvider function instead and combing setting AttributeRuntimeID attribute, and last call Wrap to wrap your TracerProvider instance.

func Wrap

Wrap registers a trace.SpanProcessor for your TraceProvider instance.

func (*TracerProviderWrapper) Tracer

func (t *TracerProviderWrapper) Tracer(name string, options ...trace.TracerOption) trace.Tracer

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL