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 ¶
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
const KeyRuntimeID attribute.Key = ext.RuntimeID
KeyRuntimeID is used to mark a process uniquely
Variables ¶
var AttributeRuntimeID = KeyRuntimeID.String(runtimeID)
var StopDDProfiler = profiler.Stop
var (
TagRuntimeID = ext.RuntimeID + ":" + runtimeID
)
Functions ¶
func StartDDProfiler ¶
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 ¶
func Wrap(tp *sdktrace.TracerProvider) *TracerProviderWrapper
Wrap registers a trace.SpanProcessor for your TraceProvider instance.
func (*TracerProviderWrapper) Tracer ¶
func (t *TracerProviderWrapper) Tracer(name string, options ...trace.TracerOption) trace.Tracer