Instrumenting Go Serverless Applications

Instrumenting Go Serverless Applications

Required setup

If not already configured, install the AWS integration. This allows Datadog to ingest Lambda metrics from AWS. After you have installed the AWS integration, follow these steps to instrument your application to send metrics, logs, and traces to Datadog.

If you previously set up Datadog Serverless using the Datadog Forwarder, see the installation instructions.

If your Go Lambda functions are still using runtime go1.x, consider either migrating to provided.al2 or using the Datadog Forwarder instead of the Datadog Lambda Extension.

Configuration

Install the Datadog Lambda library

Install the Datadog Lambda library locally by running the following command:

go get github.com/DataDog/datadog-lambda-go

Install the Datadog Lambda Extension

Add the Datadog Lambda Extension layer for your Lambda function using the ARN in the following format:

// For x86 lambdas
arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension:<EXTENSION_VERSION>
// For arm64 lambdas
arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension-ARM:<EXTENSION_VERSION>

// For x86 lambdas
arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension:<EXTENSION_VERSION>
// For arm64 lambdas
arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension-ARM:<EXTENSION_VERSION>

The latest EXTENSION_VERSION is 16.

Instrument

Follow these steps to instrument the function:

  1. Set the environment variable DD_API_KEY to your Datadog API key from API Management.

  2. Set the environment variable DD_TRACE_ENABLED to true.

  3. Import the required packages in the file declaring your Lambda function handler.

    package main
    
    import (
      "github.com/aws/aws-lambda-go/lambda"
      "github.com/DataDog/datadog-lambda-go"
      "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
      httptrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http"
    )
    
  4. Wrap your Lambda function handler using the wrapper provided by the Datadog Lambda library.

    func main() {
      // Wrap your lambda handler like this
      lambda.Start(ddlambda.WrapFunction(myHandler, nil))
      /* OR with manual configuration options
      lambda.Start(ddlambda.WrapFunction(myHandler, &ddlambda.Config{
        BatchInterval: time.Second * 15
        APIKey: "my-api-key",
      }))
      */
    }
    
  5. Use the included libraries to create additional spans, connect logs and traces, and pass trace context to other services.

    func myHandler(ctx context.Context, event MyEvent) (string, error) {
      // Trace an HTTP request
      req, _ := http.NewRequestWithContext(ctx, "GET", "https://www.datadoghq.com", nil)
      client := http.Client{}
      client = *httptrace.WrapClient(&client)
      client.Do(req)
    
      // Connect your Lambda logs and traces
      currentSpan, _ := tracer.SpanFromContext(ctx)
      log.Printf("my log message %v", currentSpan)
    
      // Create a custom span
      s, _ := tracer.StartSpanFromContext(ctx, "child.span")
      time.Sleep(100 * time.Millisecond)
      s.Finish()
    }
    

Unified service tagging

Datadog recommends tagging your serverless applications with DD_ENV, DD_SERVICE, DD_VERSION, and DD_TAGS. See the Lambda extension documentation for more details.

Explore

After configuring your function following the steps above, view your metrics, logs, and traces on the Serverless homepage.

Monitor custom business logic

If you would like to submit a custom metric, see the sample code below:

package main

import (
  "github.com/aws/aws-lambda-go/lambda"
  "github.com/DataDog/datadog-lambda-go"
)

func main() {
  // Wrap your handler function
  lambda.Start(ddlambda.WrapFunction(myHandler, nil))
}

func myHandler(ctx context.Context, event MyEvent) (string, error) {
  // Submit a custom metric
  ddlambda.Metric(
    "coffee_house.order_value", // Metric name
    12.45, // Metric value
    "product:latte", "order:online" // Associated tags
  )

  // Submit a custom metric with timestamp
  ddlambda.MetricWithTimestamp(
    "coffee_house.order_value", // Metric name
    12.45, // Metric value
    time.Now(), // Timestamp, must be within last 20 mins
    "product:latte", "order:online" // Associated tags
  )

  req, err := http.NewRequest("GET", "http://example.com/status")

  // Add the datadog distributed tracing headers
  ddlambda.AddTraceHeaders(ctx, req)

  client := http.Client{}
  client.Do(req)
}

For more information, see the Custom Metrics documentation.

If your Lambda function is running in a VPC, follow the Datadog Lambda Extension AWS PrivateLink Setup guide to ensure that the extension can reach Datadog API endpoints.

Further Reading