### all-of Join Point Example - YAML Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/all-of This example demonstrates the usage of the 'all-of' join point in a YAML configuration. It combines a 'directive' join point with a 'function' join point to match specific AST nodes. ```yaml all-of: - directive: dd:span - function: - receiver: "*net/http.RoundTripper" ``` -------------------------------- ### Select Functions by Argument Interface Implementation Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/function This example demonstrates how to select functions based on whether one of their arguments implements a specific interface, such as `context.Context`. This is useful for targeting functions that require context propagation. ```yaml function: - argument-implements: context.Context ``` -------------------------------- ### Select Function Declarations by Name and Signature Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/function This example demonstrates how to select function and method declarations based on their name and signature. It's useful for targeting specific functions within the codebase. ```yaml function: - name: main - signature: {} ``` -------------------------------- ### Aspect Configuration Example with Ordering and Namespaces Source: https://datadoghq.dev/orchestrion/adr/0002-aspect-application-order Demonstrates a configuration example for aspects, specifying 'order' and 'namespace' for advice. This allows for granular control over execution order within logical groups like 'error-handling' and 'tracing'. ```yaml aspects: - id: Error Processing advice: - prepend-statements: namespace: "error-handling" order: 10 # Execute first within namespace template: | defer func() { __result__0 = errortrace.Wrap(__result__0) }() - id: Span Creation advice: - prepend-statements: namespace: "tracing" order: 20 # Execute after error handling template: | span := tracer.StartSpan() defer func() { span.Finish(tracer.WithError(__result__0)) }() ``` -------------------------------- ### Start Datadog Profiler with Configuration Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/profiler This Go code demonstrates how to start the Datadog profiler within the `init` function of your application. It checks an environment variable for enabling profiling and configures specific profile types like CPU, Heap, Goroutine, and Mutex profiles, along with custom tags. Error handling for profiler startup is also included. ```go // Using the following synthetic imports: import ( env "github.com/DataDog/dd-trace-go/v2/instrumentation/env" log "log" profiler "github.com/DataDog/dd-trace-go/v2/profiler" ) func init() { switch env.Get("DD_PROFILING_ENABLED") { case "1", "true", "auto": // The "auto" value can be set if profiling is enabled via the // Datadog Admission Controller. We always turn on the profiler in // the "auto" case since we only send profiles after at least a // minute, and we assume anything running that long is worth // profiling. err := profiler.Start( profiler.WithProfileTypes( profiler.CPUProfile, profiler.HeapProfile, // Non-default profiles which are highly likely to be useful: profiler.GoroutineProfile, profiler.MutexProfile, ), profiler.WithTags("orchestrion:true"), ) if err != nil { // TODO: is there a better reporting mechanism? // The tracer and profiler already use the stdlib logger, so // we're not adding anything new. But users might be using a different logger. log.Printf("failed to start profiling: %s", err.Error()) } } } ``` -------------------------------- ### Install Orchestrion Tool Source: https://datadoghq.dev/orchestrion/docs/getting-started Installs the Orchestrion tool using the Go package manager. It's recommended to install it as a project tool dependency for reproducible builds. Ensure the GOBIN directory is in your PATH if needed. ```bash $ go install github.com/DataDog/orchestrion@latest ``` ```bash $ export PATH="$PATH:$(go env GOBIN)" ``` -------------------------------- ### Select Functions Whose Results Implement an Interface Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/function This example illustrates how to select functions based on whether their return value implements a specific interface, such as `io.Reader`. This is helpful for identifying functions that produce data in a standard format. ```yaml function: - result-implements: io.Reader ``` -------------------------------- ### Prepend Statements with Go Template Source: https://datadoghq.dev/orchestrion/contributing/aspects/advice/prepend-statements The `prepend-statements` advice inserts new statements rendered by a Go template before a matched AST node. This is useful for adding preamble logic to function implementations. Multiple prepend-statements are executed in reverse order. The example shows importing necessary packages and defining a template to add deferred analytics and configuration to a mux router. ```go prepend-statements: imports: ddtrace: github.com/DataDog/dd-trace-go/v2/ddtrace ext: github.com/DataDog/dd-trace-go/v2/ddtrace/ext globalconfig: github.com/DataDog/dd-trace-go/v2/internal/globalconfig http: net/http internal: github.com/DataDog/dd-trace-go/v2/internal math: math namingschema: github.com/DataDog/dd-trace-go/v2/internal/namingschema tracer: github.com/DataDog/dd-trace-go/v2/ddtrace/tracer template: "{{- $res := .Function.Result 0 -}}\ndefer func() {\n var analyticsRate float64\n if internal.BoolEnv(\"DD_TRACE_MUX_ANALYTICS_ENABLED\", false) { analyticsRate = 1.0 } else { analyticsRate = globalconfig.AnalyticsRate() } {{ $res }}.__dd_config.headerTags = globalconfig.HeaderTagMap() {{ $res }}.__dd_config.ignoreRequest = func(*http.Request) bool { return false } {{ $res }}.__dd_config.resourceNamer = ddDefaultResourceNamer {{ $res }}.__dd_config.serviceName = namingschema.ServiceName(\"mux.router\") {{ $res }}.__dd_config.spanOpts = []ddtrace.StartSpanOption{ tracer.Tag(ext.Component, \"gorilla/mux\"), tracer.Tag(ext.SpanKind, ext.SpanKindServer), } if !math.IsNaN(analyticsRate) { {{ $res }}.__dd_config.spanOpts = append( {{ $res }}.__dd_config.spanOpts, tracer.Tag(ext.EventSampleRate, analyticsRate), ) } }()" ``` -------------------------------- ### Match Function Body with Annotation and Specific Function Name Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/function-body This example demonstrates how to use the 'function-body' join point to match a block of code within a function. It specifically targets functions annotated with 'annotation' and named 'ServeHTTP'. This is useful for applying specific code transformations or analysis to targeted function bodies. ```yaml function-body: all-of: - directive: annotation - function: - name: ServeHTTP ``` -------------------------------- ### pgx.v5 Integration Setup Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-jackc-pgx To enable the pgx.v5 integration, include the specified import in your project's `orchestrion.tool.go` file. ```APIDOC ## Datadog Tracer - pgx.v5 Integration ### Description This integration enhances the pgx.v5 PostgreSQL driver with Datadog tracing capabilities. ### Setup To enable this integration, add the following import to your `orchestrion.tool.go` file: ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2" // integration // ... other imports ) ``` ### Supported Functions This integration provides tracing for the following pgx functions: - `pgx.Connect` - `pgx.ConnectConfig` - `pgxpool.New` - `pgxpool.NewWithConfig` ### Join Points and Advice The integration works by redirecting calls to the original pgx functions to their Datadog traced counterparts. This is achieved through join points and advice mechanisms within the orchestrion framework. **Connect** - **Join Point**: Call to `pgx.Connect` where the import path is not `github.com/jackc/pgx/v5` or `github.com/jackc/pgx/v5/pgxpool`. - **Advice**: Redirects the call to `github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.Connect`. **ConnectConfig** - **Join Point**: Call to `pgx.ConnectConfig` where the import path is not `github.com/jackc/pgx/v5` or `github.com/jackc/pgx/v5/pgxpool`. - **Advice**: Redirects the call to `github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.ConnectConfig`. **pgxpool.New** - **Join Point**: Call to `pgxpool.New` where the import path is not `github.com/jackc/pgx/v5` or `github.com/jackc/pgx/v5/pgxpool`. - **Advice**: Redirects the call to `github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.NewPool`. **pgxpool.NewWithConfig** - **Join Point**: Call to `pgxpool.NewWithConfig` where the import path is not `github.com/jackc/pgx/v5` or `github.com/jackc/pgx/v5/pgxpool`. - **Advice**: Redirects the call to `github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.NewPoolWithConfig`. ### Aliases - `pgx`: `github.com/jackc/pgx/v5` - `pgxpool`: `github.com/jackc/pgx/v5/pgxpool` ``` -------------------------------- ### Assign Value with Regex Compilation (Go) Source: https://datadoghq.dev/orchestrion/contributing/aspects/advice/assign-value This `assign-value` advice example shows how to assign a compiled regular expression to a variable. It requires the `regexp` package and is compatible with Go 1.18 and later. The template produces a compile-time constant value. ```yaml assign-value: imports: regexp: regexp lang: go1.18 template: "regexp.MustCompile(`^.?$|^(..+?)\1+$ `)" ``` -------------------------------- ### Instrument Gin Server Initialization with Datadog Middleware Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-gin-gonic-gin This snippet shows how to apply the Datadog tracing middleware to a Gin server. It requires synthetic imports for `gin` and the Datadog Gin integration. The middleware should be added during the server's setup. ```go // Using the following synthetic imports: import ( gin "github.com/gin-gonic/gin" gintrace "github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2" ) func() *gin.Engine { e := {{ . }} e.Use(gintrace.Middleware("")) return e }() ``` -------------------------------- ### Wrap go-redis/redis.v8 Client with Datadog Tracer Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-go-redis-redis This example demonstrates how to wrap a Redis client created with `redis.NewClient` or `redis.NewFailoverClient` using the Datadog tracer's `trace.WrapClient` function. It requires specific synthetic imports for `redis` and `trace`. ```go // Using the following synthetic imports: import ( redis "github.com/go-redis/redis/v8" trace "github.com/DataDog/dd-trace-go/contrib/go-redis/redis.v8/v2" ) func() (client *redis.Client) { client = {{ . }} trace.WrapClient(client) return }() ``` -------------------------------- ### Initialize Datadog Pub/Sub Tracer Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-cloud.google.com-go-pubsub Initializes the Datadog tracer for Google Cloud Pub/Sub v2. This involves loading the instrumentation component and creating a new Pub/Sub tracer instance. This setup is typically done once during application initialization. ```go // Using the following synthetic imports: import ( instrumentation "github.com/DataDog/dd-trace-go/v2/instrumentation" pubsubtrace "github.com/DataDog/dd-trace-go/v2/contrib/cloud.google.com/go/pubsubtrace" ) var ( __dd_instr *instrumentation.Instrumentation __dd_pstrace *pubsubtrace.Tracer ) func init() { component := instrumentation.PackageGCPPubsubV2 __dd_instr = instrumentation.Load(component) __dd_pstrace = pubsubtrace.NewTracer(__dd_instr, component) } ``` -------------------------------- ### Kafka Reader FetchMessage Span Creation Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-segmentio-kafka-go This code snippet demonstrates how to prepend statements to the `FetchMessage` function body to initialize the reader's tracer, manage spans, and start a consume span for each message fetched. It ensures proper span lifecycle management. ```go // Using the following synthetic imports: import ( tracing "github.com/DataDog/dd-trace-go/contrib/segmentio/kafka-go/v2/internal/tracing" ) {{- $r := .Function.Receiver -}} {{- $ctx := .Function.Argument 0 -}} {{- $msg := .Function.Result 0 -}} {{- $err := .Function.Result 1 -}} __dd_initReader(r) if {{ $r }}.__dd_prevSpan != nil { {{ $r }}.__dd_prevSpan.Finish() {{ $r }}.__dd_prevSpan = nil } defer func() { if {{ $err }} != nil { return } tMsg := __dd_wrapMessage(&{{ $msg }}) {{ $r }}.__dd_prevSpan = {{ $r }}.__dd_tracer.StartConsumeSpan({{ $ctx }}, tMsg) {{ $r }}.__dd_tracer.SetConsumeDSMCheckpoint(tMsg) }() ``` -------------------------------- ### Enable Orchestrion Profiling and Analyze with `go tool pprof` Source: https://datadoghq.dev/orchestrion/contributing/performance This snippet demonstrates how to enable CPU profiling in Orchestrion using command-line arguments and then analyze the generated profiles with `go tool pprof`. It covers setting the profile output directory, enabling the CPU profiler, and then using `go tool pprof` to combine and visualize the profiles. ```bash $ orchestrion --profile-path="$PWD/profiles" --profile=cpu go build . $ go tool pprof -proto $PWD/profiles/*.pprof > profile.pprof $ go tool pprof -http=localhost:6060 profile.pprof ``` -------------------------------- ### Redirect pgx.ConnectConfig to Traced Version Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-jackc-pgx For configuring pgx.v5 connections, calls to `pgx.ConnectConfig` should be redirected to `github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.ConnectConfig`. This allows tracing of connection setup using configurations. ```go // Original call: // cfg, err := pgx.ParseConfig(connStr) // if err != nil { // // handle error // } // conn, err := pgx.ConnectConfig(ctx, cfg) // Redirected call: // cfg, err := pgx.ParseConfig(connStr) // if err != nil { // // handle error // } // conn, err := github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.ConnectConfig(ctx, cfg) ``` -------------------------------- ### Instrument Sarama NewSyncProducer with Datadog Tracer Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-shopify-sarama This example demonstrates how to instrument `sarama.NewSyncProducer` or `sarama.NewSyncProducerFromClient` calls with Datadog tracing. It conditionally applies the configuration if available. ```go // Using the following synthetic imports: import ( sarama "github.com/Shopify/sarama" saramatrace "github.com/DataDog/dd-trace-go/contrib/Shopify/sarama/v2" ) {{- $cfg := .Function.ArgumentOfType "sarama.Config" -}} func(p sarama.SyncProducer, err error) (sarama.SyncProducer, error) { if p != nil { p = saramatrace.WrapSyncProducer( {{- if $cfg -}} {{ $cfg }}, {{- else -}} nil, {{- end -}} p, ) } return p, err }({{ . }}) ``` -------------------------------- ### Start Span from Context using dd-trace-go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/custom-trace This snippet demonstrates how to manually create a span from an existing context using the `dd-trace-go` library. It's useful for instrumenting specific code sections without refactoring or when custom span configurations are needed. Ensure the `dd-trace-go` library is imported. ```go import ( "context" "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" ) func myFunc(ctx context.Context) { // Start a new span from the context span, ctx := tracer.StartSpanFromContext(ctx, "my.custom.operation") defer span.Finish() // Your code here... } ``` -------------------------------- ### Initialize and Stop Datadog Tracer in Go Main Function Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/ddtrace-tracer Sets up the Datadog Tracer to start automatically at application initialization and stop gracefully upon exiting the main function in Go. This ensures all traces are captured and flushed. ```go func init() { tracer.Start() } defer tracer.Stop() ``` -------------------------------- ### Configure MongoDB Client with Datadog Monitor Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-go.mongodb.org-mongo-driver This example demonstrates how to configure the MongoDB client to use the Datadog monitor. This is achieved by calling `SetMonitor` on the client with a new monitor created by `mongotrace.NewMonitor()`. Ensure you have the correct synthetic imports. ```go // Using the following synthetic imports: import ( mongotrace "github.com/DataDog/dd-trace-go/contrib/go.mongodb.org/mongo-driver.v2/v2/mongo" options "go.mongodb.org/mongo-driver/v2/mongo/options" ) {{ . }}.SetMonitor(mongotrace.NewMonitor()) ``` -------------------------------- ### Custom Datadog Tracer Integrations with Orchestrion (Go) Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go This Go code snippet illustrates how to customize Datadog tracer integrations within Orchestrion. Instead of the default 'all' integration, it imports specific packages like the core tracer and the HTTP client/server integrations, allowing for a more targeted tracing setup. ```go //go:build tools //go:generate go run github.com/DataDog/orchestrion pin package tools // Imports in this file determine which tracer integrations are enabled in // orchestrion. New integrations can be automatically discovered by running // `orchestrion pin` again. You can also manually add new imports here to // enable additional integrations. When doing so, you can run `orchestrion pin` // to make sure manually added integrations are valid (i.e, the imported package // includes a valid `orchestrion.yml` file). import ( // Ensures `orchestrion` is present in `go.mod` so that builds are repeatable. // Do not remove. _ "github.com/DataDog/orchestrion" // Provides integrations for essential `orchestrion` features. Most users // should not remove this integration. _ "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" // integration _ "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http" // integration ) ``` -------------------------------- ### Build with Orchestrion using 'orchestrion go' Source: https://datadoghq.dev/orchestrion/docs/getting-started Recommends using 'orchestrion go' as a replacement for standard 'go' commands to build, run, or test your project with Orchestrion instrumentation. ```bash $ orchestrion go build . $ orchestrion go run . $ orchestrion go test ./... ``` -------------------------------- ### Kafka Writer Tracing Initialization Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-segmentio-kafka-go This section provides the necessary synthetic imports and the `__dd_initWriter` function for initializing the Datadog tracer for Kafka Writer operations. It configures the tracer with bootstrap servers and other relevant Kafka details. ```go // Using the following synthetic imports: import ( tracing "github.com/DataDog/dd-trace-go/contrib/segmentio/kafka-go/v2/internal/tracing" ) func __dd_initWriter(w *Writer) { if w.__dd_tracer != nil { return } kafkaCfg := tracing.KafkaConfig{ BootstrapServers: w.Addr.String(), } w.__dd_tracer = tracing.NewTracer(kafkaCfg) } ``` -------------------------------- ### Assign Value with Compile-Time Constant (Go) Source: https://datadoghq.dev/orchestrion/contributing/aspects/advice/assign-value The `assign-value` advice modifies the initial value of a package-level `var` or `const` declaration. When matching a `const`, the template must yield only compile-time constant values. This example demonstrates assigning a boolean literal. ```yaml assign-value: template: "true" ``` -------------------------------- ### Kafka Reader Tracing Enhancements Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-segmentio-kafka-go This section details the synthetic imports, wrapper types, and initialization logic required for tracing Kafka Reader operations. It includes wrappers for messages and headers, and a tracer initialization function. ```go // Using the following synthetic imports: import ( strings "strings" tracer "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" tracing "github.com/DataDog/dd-trace-go/contrib/segmentio/kafka-go/v2/internal/tracing" ) type __dd_wMessage struct { *Message } func __dd_wrapMessage(msg *Message) tracing.Message { if msg == nil { return nil } return &__dd_wMessage{msg} } func (w *__dd_wMessage) GetValue() []byte { return w.Value } func (w *__dd_wMessage) GetKey() []byte { return w.Key } func (w *__dd_wMessage) GetHeaders() []tracing.Header { hs := make([]tracing.Header, 0, len(w.Headers)) for _, h := range w.Headers { hs = append(hs, __dd_wrapHeader(h)) } return hs } func (w *__dd_wMessage) SetHeaders(headers []tracing.Header) { hs := make([]Header, 0, len(headers)) for _, h := range headers { hs = append(hs, Header{ Key: h.GetKey(), Value: h.GetValue(), }) } w.Message.Headers = hs } func (w *__dd_wMessage) GetTopic() string { return w.Topic } func (w *__dd_wMessage) GetPartition() int { return w.Partition } func (w *__dd_wMessage) GetOffset() int64 { return w.Offset } type __dd_wHeader struct { Header } func __dd_wrapHeader(h Header) tracing.Header { return &__dd_wHeader{h} } func (w __dd_wHeader) GetKey() string { return w.Key } func (w __dd_wHeader) GetValue() []byte { return w.Value } type __dd_wWriter struct { *Writer } func (w *__dd_wWriter) GetTopic() string { return w.Topic } func __dd_wrapTracingWriter(w *Writer) tracing.Writer { return &__dd_wWriter{w} } func __dd_initReader(r *Reader) { if r.__dd_tracer != nil { return } kafkaCfg := tracing.KafkaConfig{} if r.Config().Brokers != nil { kafkaCfg.BootstrapServers = strings.Join(r.Config().Brokers, ",") } if r.Config().GroupID != "" { kafkaCfg.ConsumerGroupID = r.Config().GroupID } r.__dd_tracer = tracing.NewTracer(kafkaCfg) } type __dd_tracer_Span = tracer.Span ``` -------------------------------- ### Instrument http Client Calls (Get, Head, Post, PostForm) Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-net-http Replaces standard http client calls (Get, Head, Post, PostForm) with Datadog's instrumented versions from the `client` package. This ensures that outgoing HTTP requests are traced. ```go // Using the following synthetic imports: import ( __ddtrace_client "github.com/DataDog/dd-trace-go/contrib/net/http/v2/client" ) // Example for http.Get: __ddtrace_client.Get( ctx, url ) ``` -------------------------------- ### Instrument Valkey Client Creation with Datadog Tracer Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-valkey-io-valkey-go This code demonstrates how to instrument the `valkey.NewClient` call using the Datadog Tracer for Go. It replaces the original client creation with a traced version, allowing for monitoring of Valkey operations. ```go // Using the following synthetic imports: import ( valkeytrace "github.com/DataDog/dd-trace-go/contrib/valkey-io/valkey-go/v2" ) valkeytrace.NewClient({{ index .AST.Args 0 }}) ``` -------------------------------- ### Register Orchestrion in go.mod Source: https://datadoghq.dev/orchestrion/docs/getting-started Registers Orchestrion in your project's go.mod file to ensure reproducible builds. This command should be run after installing Orchestrion. ```bash $ orchestrion pin ``` -------------------------------- ### Instrument Go common.Parallel Function Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/internal-civisibility-integrations-gotesting Prepends a deferred call to instrument the common.Parallel function in Go. It uses __dd_civisibility_instrumentTestingParallel to manage parallel test execution, ensuring proper setup and teardown. ```go defer func() { _ = __dd_civisibility_instrumentTestingParallel({{ .Function.Receiver }}) }() ``` -------------------------------- ### Redirect pgxpool.NewWithConfig to Traced Version Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-jackc-pgx For creating pgxpool instances with specific configurations, calls to `pgxpool.NewWithConfig` should be redirected to `github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.NewPoolWithConfig`. This enables tracing of connection pool initialization with custom settings. ```go // Original call: // cfg, err := pgxpool.ParseConfig(connStr) // if err != nil { // // handle error // } // pool, err := pgxpool.NewWithConfig(ctx, cfg) // Redirected call: // cfg, err := pgxpool.ParseConfig(connStr) // if err != nil { // // handle error // } // pool, err := github.com/DataDog/dd-trace-go/contrib/jackc/pgx.v5/v2.NewPoolWithConfig(ctx, cfg) ``` -------------------------------- ### Enable Datadog Tracer Integration in Go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/ddtrace-tracer Enables Datadog Tracer integrations by adding a specific import to the project's orchestrion.tool.go file. This setup is crucial for activating tracing capabilities within the application. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" // integration //... ) ``` -------------------------------- ### Match Any Node Not Matched by Specified Join Point (YAML) Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/not The `not` join point is node-agnostic and matches any node that is not matched by the specified join point. It is used to exclude certain directives or functions from being matched. ```yaml not: directive: dd:span ``` ```yaml not: function: - receiver: net/http.Server ``` -------------------------------- ### Build with Orchestrion using GOFLAGS Source: https://datadoghq.dev/orchestrion/docs/getting-started Explains how to set the '-toolexec' argument in the GOFLAGS environment variable for seamless integration of Orchestrion. This allows using standard 'go' commands after the variable is set. ```bash $ export GOFLAGS="${GOFLAGS} '-toolexec=orchestrion toolexec'" $ go build . $ go run . $ go test ./... ``` -------------------------------- ### Enable go-redis/redis.v8 Integration in Go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-go-redis-redis To enable the go-redis/redis.v8 integration, include the specified import in your project's `orchestrion.tool.go` file. This ensures the Datadog tracer can instrument Redis client calls. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/go-redis/redis.v8/v2" // integration //... ) ``` -------------------------------- ### Match Package by Name (Orchestrion) Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/package-name The `package-name` join point is a node-agnostic feature used to match any node within a package of a specified name. It is commonly employed for instrumenting code within the `main` package. ```Orchestrion package-name: main ``` -------------------------------- ### Enable OS Integration in Orchestrion Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-os To enable OS integrations, include the specified import in your project's `orchestrion.tool.go` file. This ensures the Datadog tracer can monitor OS-level operations. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/v2/contrib/os" // integration //... ) ``` -------------------------------- ### Replace Function Call with Designated Function Source: https://datadoghq.dev/orchestrion/contributing/aspects/advice/replace-function The `replace-function` advice allows for the replacement of a callee in a `Call` node, typically identified by `function-call`. Both the current and replacement functions must possess compatible signatures for this operation to succeed. ```go replace-function: github.com/DataDog/dd-trace-go/contrib/gorm.io/gorm.v1/v2.Open ``` -------------------------------- ### Build with Orchestrion using -toolexec flag Source: https://datadoghq.dev/orchestrion/docs/getting-started Demonstrates how to manually specify the '-toolexec' argument to Go commands to integrate Orchestrion instrumentation. This method requires explicitly passing the 'orchestrion toolexec' command. ```bash $ go build -toolexec 'orchestrion toolexec' . $ go run -toolexec 'orchestrion toolexec' . $ go test -toolexec 'orchestrion toolexec' ./... ``` -------------------------------- ### Match Struct Literal by Pointer Type Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/struct-literal This example shows how to use the 'struct-literal' join point with the 'pointer-only' match option to specifically target struct literals where the address is taken. This is useful for intercepting operations on pointers to structs. ```yaml struct-literal: match: pointer-only type: net/http.Transport ``` -------------------------------- ### Enable Datadog Tracer for Rueidis (Go) Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-redis-rueidis Enables the Datadog Tracer integration for the rueidis Redis client by adding specific imports to your project's main Go file. This setup is required before using the instrumented client. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/redis/rueidis/v2" // integration //... ) ``` -------------------------------- ### Enable Datadog Tracer for gqlgen in orchestrion.tool.go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-99designs-gqlgen To enable Datadog tracing for gqlgen, include the specified import statements in your project's `orchestrion.tool.go` file. This ensures the Datadog tracer is aware of and can instrument gqlgen operations. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/99designs/gqlgen/v2" // integration //... ) ``` -------------------------------- ### Configure GORM Open with Datadog Trace Plugin in Go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-gorm.io-gorm This Go code demonstrates how to configure the gorm.Open call to include the Datadog trace plugin. It defines synthetic imports for gorm and the trace plugin, then wraps the database opening logic to ensure the DDTracePlugin is registered. This is crucial for enabling Datadog's performance monitoring for GORM operations. ```go // Using the following synthetic imports: import ( gorm "gorm.io/gorm" gormtrace "github.com/DataDog/dd-trace-go/contrib/gorm.io/gorm.v1/v2" ) func() (*gorm.DB, error) { db, err := {{ . }} if err != nil { return nil, err } if _, ok := db.Plugins["DDTracePlugin"]; ok { return db, nil } if err := db.Use(gormtrace.NewTracePlugin()); err != nil { return nil, err } return db, nil }() ``` -------------------------------- ### Select Functions Whose Final Results Implement an Error Interface Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/function This snippet focuses on selecting functions where the final result implements the `error` interface. This is crucial for error handling and identifying functions that might return errors. ```yaml function: - final-result-implements: error ``` -------------------------------- ### Kafka Consumer and Producer Initialization (Go) Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-confluentinc-confluent-kafka-go-kafka Initializes DataDog tracers for Kafka consumers and producers. This involves creating new tracers, optionally configuring them with provided options, and wrapping the relevant channels (events, produce) to inject tracing context. ```Go func init() { __dd_instr = kafkatrace.Package(__dd_ckgoVersion) } func __dd_newKafkaTracer(opts ...kafkatrace.Option) *kafkatrace.Tracer { v, _ := LibraryVersion() return kafkatrace.NewKafkaTracer(__dd_instr, __dd_ckgoVersion, v, opts...) } func __dd_initConsumer(c *Consumer) { if c.__dd_tracer != nil { return } var opts []kafkatrace.Option if c.__dd_confmap != nil { opts = append(opts, kafkatrace.WithConfig(__dd_wrapConfigMap(c.__dd_confmap))) } c.__dd_tracer = __dd_newKafkaTracer(opts...) // TODO: accessing c.events here might break if the library renames this variable... c.__dd_events = kafkatrace.WrapConsumeEventsChannel(c.__dd_tracer, c.events, c, __dd_wrapEvent) } func __dd_initProducer(p *Producer) { if p.__dd_tracer != nil { return } p.__dd_tracer = __dd_newKafkaTracer() // TODO: accessing p.events and p.produceChannel here might break if the library renames this variable... p.__dd_events = p.events p.__dd_produceChannel = kafkatrace.WrapProduceChannel(p.__dd_tracer, p.produceChannel, __dd_wrapMessage) if p.__dd_tracer.DSMEnabled() { p.__dd_events = kafkatrace.WrapProduceEventsChannel(p.__dd_tracer, p.events, __dd_wrapEvent) } } type __dd_eventChan = chan Event type __dd_messageChan = chan *Message ``` -------------------------------- ### Add Datadog Tracer to graphql-go Schema Parsing Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-graph-gophers-graphql-go This example demonstrates how to add a Datadog tracer to your graphql-go schema parsing calls. It involves using synthetic imports for graphql and graphqltrace, and then appending the `graphql.Tracer` with `graphqltrace.NewTracer()` to the schema parsing function. ```go // Using the following synthetic imports: import ( graphql "github.com/graph-gophers/graphql-go" graphqltrace "github.com/DataDog/dd-trace-go/contrib/graph-gophers/graphql-go/v2" ) graphql.Tracer(graphqltrace.NewTracer()) ``` -------------------------------- ### Enable Gin Integration in Go Project Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-gin-gonic-gin To enable the Gin integration, add the specified import to your project's `orchestrion.tool.go` file. This ensures the Datadog tracer can automatically instrument Gin-related calls. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2" // integration //... ) ``` -------------------------------- ### Instrument Twirp Server Options with Datadog Hooks in Go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-twitchtv-twirp This Go code snippet demonstrates how to instrument Twirp server options by replacing the expression for `twirp.ServerOptions`. It integrates Datadog's server hooks using `twirptrace.NewServerHooks()` and chains them with existing hooks if present. ```go // Using the following synthetic imports: import ( twirp "github.com/twitchtv/twirp" twirptrace "github.com/DataDog/dd-trace-go/contrib/twitchtv/twirp/v2" ) {{.AST.Type}}{ {{- $hasField := false -}} {{ range .AST.Elts }} {{- if eq .Key.Name "Hooks" }} {{- $hasField = true -}} Hooks: twirp.ChainHooks(twirptrace.NewServerHooks(), {{ .Value }}), {{- else -}} {{ . }}, {{ end -}} {{ end }} {{- if not $hasField -}} Hooks: twirptrace.NewServerHooks(), {{- end }} } ``` -------------------------------- ### Update PublishResult.Get for Tracing Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-cloud.google.com-go-pubsub Modifies the `Get` method of `pubsub.PublishResult` to invoke the `DDCloseSpan` function upon completion. This ensures that the associated trace span is properly closed, passing the server ID and any error that occurred during the publish operation. ```go {{- $publishResult := .Function.Receiver -}} {{- $serverID := .Function.Result 0 -}} {{- $err := .Function.Result 1 -}} deffer func() { if {{ $publishResult }}.DDCloseSpan != nil { {{ $publishResult }}.DDCloseSpan({{ $serverID }}, {{ $err }}) } }() ``` -------------------------------- ### Enable graphql-go Integration in orchestrion.tool.go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-graphql-go-graphql To enable the graphql-go integration, add the specified import statement to your orchestrion.tool.go file. This ensures that the Datadog tracer can automatically instrument your GraphQL calls. No additional configuration is typically required beyond this import. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/graphql-go/graphql/v2" // integration //... ) ``` -------------------------------- ### Select Functions with Specific Argument and Return Types Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/function This snippet shows how to filter functions by the types of their arguments and return values. It allows for precise selection of functions that adhere to certain type contracts, such as accepting `context.Context` and returning an `error`. ```yaml function: - signature-contains: args: - context.Context returns: - error ``` -------------------------------- ### Match Any Node with 'one-of' Join Point (YAML) Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/one-of The 'one-of' join point matches any node that satisfies at least one of its child join points. This is useful for defining multiple alternative conditions, often with repeated instances of the same join point type. ```yaml one-of: - function-call: google.golang.org/grpc.Dial - function-call: google.golang.org/grpc.DialContext - function-call: google.golang.org/grpc.NewClientConn ``` -------------------------------- ### Instrument Gorilla Mux ServeHTTP for Datadog Tracing Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-gorilla-mux This Go code snippet instruments the `ServeHTTP` method of a `mux.Router` for Datadog tracing. It lazily initializes the Datadog configuration, sets up span options, and uses `httptrace.TraceAndServe` to trace incoming requests. It includes logic to ignore requests within the tracing wrapper to prevent recursion and correctly extracts route information for span tags. ```go // Using the following synthetic imports: import ( ext "github.com/DataDog/dd-trace-go/v2/ddtrace/ext" http "net/http" httptrace "github.com/DataDog/dd-trace-go/contrib/net/http/v2" instrhttptrace "github.com/DataDog/dd-trace-go/v2/instrumentation/httptrace" instrumentation "github.com/DataDog/dd-trace-go/v2/instrumentation" math "math" options "github.com/DataDog/dd-trace-go/v2/instrumentation/options" sync "sync" tracer "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" ) {{- $r := .Function.Receiver -}} {{- $w := .Function.Argument 0 -}} {{- $req := .Function.Argument 1 -}} // Lazy-initialize dd_config on first request to handle subrouter usage if {{ $r }}.__dd_config.initOnce == nil { {{ $r }}.__dd_config.initOnce = &sync.Once{} } {{ $r }}.__dd_config.initOnce.Do(func() { analyticsRate := __dd_instr.AnalyticsRate(true) {{ $r }}.__dd_config.headerTags = __dd_instr.HTTPHeadersAsTags() {{ $r }}.__dd_config.serviceName = __dd_instr.ServiceName(instrumentation.ComponentServer, nil) {{ $r }}.__dd_config.resourceNamer = ddDefaultResourceNamer {{ $r }}.__dd_config.ignoreRequest = func(_ *http.Request) bool { return false } {{ $r }}.__dd_config.spanOpts = []tracer.StartSpanOption{ tracer.Tag(ext.Component, instrumentation.PackageGorillaMux), tracer.Tag(ext.SpanKind, ext.SpanKindServer), } if !math.IsNaN(analyticsRate) { {{ $r }}.__dd_config.spanOpts = append( {{ $r }}.__dd_config.spanOpts, tracer.Tag(ext.EventSampleRate, analyticsRate), ) } }) if !{{ $r }}.__dd_config.ignoreRequest({{ $req }}) { var ( match RouteMatch route string spanOpts = options.Copy({{ $r }}.__dd_config.spanOpts) ) if {{ $r }}.Match({{ $req }}, &match) && match.Route != nil { if h, err := match.Route.GetHostTemplate(); err == nil { spanOpts = append(spanOpts, tracer.Tag("mux.host", h)) } route, _ = match.Route.GetPathTemplate() } spanOpts = append(spanOpts, instrhttptrace.HeaderTagsFromRequest({{ $req }}, {{ $r }}.__dd_config.headerTags)) resource := {{ $r }}.__dd_config.resourceNamer({{ $r }}, {{ $req }}) // This is a temporary workaround/hack to prevent endless recursion via httptrace.TraceAndServe, which // basically implies passing a shallow copy of this router that ignores all requests down to // httptrace.TraceAndServe. var rCopy Router rCopy = *{{ $r }} rCopy.__dd_config.ignoreRequest = func(*http.Request) bool { return true } httptrace.TraceAndServe(&rCopy, {{ $w }}, {{ $req }}, &httptrace.ServeConfig{ Service: {{ $r }}.__dd_config.serviceName, Resource: resource, SpanOpts: spanOpts, RouteParams: match.Vars, Route: route, }) return } ``` -------------------------------- ### Match Struct Literal by Field and Type Source: https://datadoghq.dev/orchestrion/contributing/aspects/join-points/struct-literal This example demonstrates how to use the 'struct-literal' join point to match a struct literal based on a specific field name and the struct's type. It's useful for targeting specific initializations within a larger struct. ```yaml struct-literal: field: Handler type: net/http.Server ``` -------------------------------- ### Wrap Expression with Chi Middleware in Go Source: https://datadoghq.dev/orchestrion/contributing/aspects/advice/wrap-expression Wraps a matched node with a code template to apply Chi middleware for tracing. This is useful for integrating DataDog tracing into Chi router instances. It ensures the expression type is maintained. Imports for chi and chitrace are necessary. ```yaml wrap-expression: imports: chi: github.com/go-chi/chi chitrace: github.com/DataDog/dd-trace-go/contrib/go-chi/chi/v2 template: |- func() *chi.Mux { mux := {{ . }} mux.Use(chitrace.Middleware()) return mux }() ``` -------------------------------- ### Enable gocql Integration in Go Project Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-gocql-gocql Enables the gocql integration by adding specific import paths to the `orchestrion.tool.go` file. This is a prerequisite for using Datadog tracing with gocql. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/gocql/gocql/v2" // integration //... ) ``` -------------------------------- ### Instrument http.Get, Head, Post, PostForm calls Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-net-http This snippet demonstrates how to instrument common HTTP client functions like `http.Get`, `http.Head`, `http.Post`, and `http.PostForm`. It replaces these calls with versions from the `__ddtrace_client` package, ensuring context propagation. ```go import ( __ddtrace_client "github.com/DataDog/dd-trace-go/contrib/net/http/v2/client" ) // ... other code ... // Example for http.Get func Get(url string) (*http.Response, error) { return __ddtrace_client.Get(context.Background(), url) } // Example for http.Post func Post(url, contentType string, body io.Reader) (*http.Response, error) { return __ddtrace_client.Post(context.Background(), url, contentType, body) } ``` -------------------------------- ### Global State Management for Datadog Tracer in Go Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/ddtrace-tracer Implements global state management for the Datadog Tracer using `__dd_gls_v2` within Go's runtime. This involves adding a new field to `runtime.g` and providing functions to get and set this global state, along with necessary imports. ```go //go:linkname __dd_orchestrion_gls_get __dd_orchestrion_gls_get.V2 var __dd_orchestrion_gls_get = func() any { return getg().m.curg.__dd_gls_v2 } //go:linkname __dd_orchestrion_gls_set __dd_orchestrion_gls_set.V2 var __dd_orchestrion_gls_set = func(val any) { getg().m.curg.__dd_gls_v2 = val } ``` -------------------------------- ### Enable Datadog Tracer for kafka-go Integration Source: https://datadoghq.dev/orchestrion/docs/dd-trace-go/v2/contrib-segmentio-kafka-go To enable the Datadog integration for kafka-go, include the specified import in your project's orchestrion.tool.go file. This ensures the tracer is available for Kafka operations. ```go import ( _ "github.com/DataDog/orchestrion" _ "github.com/DataDog/dd-trace-go/contrib/segmentio/kafka-go/v2" // integration //... ) ``` -------------------------------- ### Define Structs and Functions with Go Linkname - inject-declarations Source: https://datadoghq.dev/orchestrion/contributing/aspects/advice/inject-declarations This snippet demonstrates using `inject-declarations` to define custom structs like `ddRouterConfig` and functions such as `ddDefaultResourceNamer`. It also includes initialization logic to load integrations and mark them as imported, requiring imports for `ddtrace`, `http`, `internal`, `telemetry`, and `tracer`. ```go inject-declarations: imports: ddtrace: github.com/DataDog/dd-trace-go/v2/ddtrace http: net/http internal: github.com/DataDog/dd-trace-go/v2/internal telemetry: github.com/DataDog/dd-trace-go/v2/internal/telemetry tracer: github.com/DataDog/dd-trace-go/v2/ddtrace/tracer template: |- type ddRouterConfig struct { ignoreRequest func(*http.Request) bool headerTags *internal.LockMap resourceNamer func(*Router, *http.Request) string serviceName string spanOpts []ddtrace.StartSpanOption } func ddDefaultResourceNamer(router *Router, req *http.Request) string { var ( match RouteMatch route = "unknown" ) if router.Match(req, &match) && match.Route != nil { if r, err := match.Route.GetPathTemplate(); err == nil { route = r } } return fmt.Sprintf("%s %s", req.Method, route) } func init() { telemetry.LoadIntegration("gorilla/mux") tracer.MarkIntegrationImported("github.com/gorilla/mux") } ```