Azure Container Apps Instrumentation

Instrumentation method

Runtime

Instrumentation method


AspectIn-ContainerSidecar
DeploymentOne container (your app, wrapped with the Datadog Agent)Two containers (your app, Datadog Agent)
Image changesIncreases app image size.No change to app image.
Cost overheadLess than sidecar (no extra container).Extra vCPU/memory. Overallocating the sidecar wastes resources; underallocating leads to premature scaling.
LoggingDirect stdout/stderr access.Requires a shared volume and log library routing to a log file. Uncaught errors require extra handling, since they are not automatically handled by your logging library.
Failure isolationIn rare cases, Datadog Agent bugs can affect your app.Datadog Agent faults are isolated.
Best forSimpler setup, lower cost, and direct log piping.Multiple containers per service, Agent isolation, and performance-sensitive workloads.

In-Container: Python

Install the Datadog Python SDK

Add ddtrace to your requirements.txt or pyproject.toml. You can find the latest version on PyPI:

requirements.txt

ddtrace==<VERSION>

Alternatively, you can install the SDK in your Dockerfile:

Dockerfile

RUN pip install ddtrace

Then, wrap your start command with ddtrace-run:

Dockerfile

CMD ["ddtrace-run", "python", "app.py"]

For more information, see Tracing Python applications.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["ddtrace-run", "python", "path/to/your/python/app.py"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "ddtrace-run", "python", "path/to/your/python/app.py"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "ddtrace-run", "python", "path/to/your/python/app.py"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends the following environment variables:

  • ENV PYTHONUNBUFFERED=1: Makes Python output appear immediately in container logs instead of being buffered.
  • ENV DD_LOGS_INJECTION=true: Enable log/trace correlation for supported loggers.
  • ENV DD_SOURCE=python: Enable advanced Datadog log parsing.

If you want multiline logs to be preserved in a single log message, Datadog recommends writing your logs in JSON format. For example, you can use a third-party logging library such as structlog:

import structlog

def tracer_injection(logger, log_method, event_dict):
    event_dict.update(tracer.get_log_correlation_context())
    return event_dict

structlog.configure(
    processors=[
        tracer_injection,
        structlog.processors.EventRenamer("msg"),
        structlog.processors.JSONRenderer()
    ],
    logger_factory=structlog.WriteLoggerFactory(file=sys.stdout),
)

logger = structlog.get_logger()

logger.info("Hello world!")

For more information, see Correlating Python Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Enable profiling (preview)

To enable the Continuous Profiler, set the environment variable DD_PROFILING_ENABLED=true.

Datadog's Continuous Profiler is available in preview for Azure Container Apps.

In-Container: Node.js

Install the Datadog Node.js SDK

In your main application, install the dd-trace package.

npm install dd-trace

Initialize the Node.js tracer with the NODE_OPTIONS environment variable:

Dockerfile

ENV NODE_OPTIONS="--require dd-trace/init"

For more information, see Tracing Node.js applications.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["/nodejs/bin/node", "/path/to/your/app.js"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "/nodejs/bin/node", "/path/to/your/app.js"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "/nodejs/bin/node", "/path/to/your/app.js"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends setting the environment variables DD_LOGS_INJECTION=true and DD_SOURCE=nodejs to enable advanced Datadog log parsing.

If you want multiline logs to be preserved in a single log message, Datadog recommends writing your logs in JSON format. For example, you can use a third-party logging library such as winston:

const { createLogger, format, transports } = require('winston');

const logger = createLogger({
  level: 'info',
  exitOnError: false,
  format: format.json(),
  transports: [
    new transports.Console()
  ],
});

logger.info('Hello world!');

For more information, see Correlating Node.js Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, view code examples. In serverless, only the distribution metric type is supported.

Enable profiling (preview)

To enable the Continuous Profiler, set the environment variable DD_PROFILING_ENABLED=true.

Datadog's Continuous Profiler is available in preview for Azure Container Apps.

In-Container: Go

Install the Datadog Go SDK

In your main application, add the SDK from dd-trace-go.

go get github.com/DataDog/dd-trace-go/v2/ddtrace/tracer

Add the following to your application code to initialize the tracer:

tracer.Start()
defer tracer.Stop()

You can also add additional packages:

# Enable Profiling
go get github.com/DataDog/dd-trace-go/v2/profiler

# Patch /net/http
go get github.com/DataDog/dd-trace-go/contrib/net/http/v2

For more information, see Tracing Go Applications and the Tracer README.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["./your-binary"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "./your-binary"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "./your-binary"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends setting the environment variable DD_SOURCE=go to enable advanced Datadog log parsing.

If you want multiline logs to be preserved in a single log message, Datadog recommends writing your logs in JSON format. For example, you can use a third-party logging library such as logrus:

logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.AddHook(&dd_logrus.DDContextLogHook{})

logrus.WithContext(ctx).Info("Hello World!")

For more information, see Correlating Go Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

In-Container: Java

Install the Datadog Java SDK

Add the Datadog Java SDK to your Dockerfile:

Dockerfile

ADD 'https://dtdg.co/latest-java-tracer' agent.jar
ENV JAVA_TOOL_OPTIONS="-javaagent:agent.jar"

Add the SDK artifacts.

<dependency>
  <groupId>com.datadoghq</groupId>
  <artifactId>dd-trace-api</artifactId>
  <version>DD_TRACE_JAVA_VERSION_HERE</version>
</dependency>
implementation 'com.datadoghq:dd-trace-api:DD_TRACE_JAVA_VERSION_HERE'

See dd-trace-java releases for the latest tracer version.

Add the @Trace annotation to any method you want to trace.

For more information, see Tracing Java Applications.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["./mvnw", "spring-boot:run"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "./mvnw", "spring-boot:run"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "./mvnw", "spring-boot:run"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends setting the environment variables DD_LOGS_INJECTION=true and DD_SOURCE=java to enable advanced Datadog log parsing.

If you want multiline logs to be preserved in a single log message, Datadog recommends writing your logs in compact JSON format. For example, you can use a third-party logging library such as Log4j 2:

private static final Logger logger = LogManager.getLogger(App.class);
logger.info("Hello World!");

resources/log4j2.xml

<Configuration>
  <Appenders>
    <Console name="Console"><JsonLayout compact="true" eventEol="true" properties="true"/></Console>
  </Appenders>
  <Loggers><Root level="info"><AppenderRef ref="Console"/></Root></Loggers>
</Configuration>

For more information, see Correlating Java Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

In-Container: .NET

Install the Datadog .NET SDK

Install the Datadog .NET SDK in your Dockerfile.

Because GitHub requests are rate limited, you must pass a GitHub token saved in the environment variable GITHUB_TOKEN as a Docker build secret --secret id=github-token,env=GITHUB_TOKEN.

Dockerfile

RUN --mount=type=secret,id=github-token,env=GITHUB_TOKEN \
    chmod +x /app/dotnet.sh && /app/dotnet.sh

Dockerfile

# For alpine use datadog-dotnet-apm-2.57.0-musl.tar.gz
ARG TRACER_VERSION
ADD https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm-${TRACER_VERSION}.tar.gz /tmp/datadog-dotnet-apm.tar.gz

RUN mkdir -p /dd_tracer/dotnet/ && tar -xzvf /tmp/datadog-dotnet-apm.tar.gz -C /dd_tracer/dotnet/ && rm /tmp/datadog-dotnet-apm.tar.gz

For more information, see Tracing .NET applications.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["dotnet", "dotnet.dll"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "dotnet", "dotnet.dll"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "dotnet", "dotnet.dll"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends setting the environment variables DD_LOGS_INJECTION=true and DD_SOURCE=csharp to enable advanced Datadog log parsing.

If you want multiline logs to be preserved in a single log message, Datadog recommends writing your logs in JSON format. For example, you can use a third-party logging library such as Serilog:

using Serilog;

builder.Host.UseSerilog((context, config) =>
{
    config.WriteTo.Console(new Serilog.Formatting.Json.JsonFormatter(renderMessage: true));
});

logger.LogInformation("Hello World!");

For more information, see Correlating .NET Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

In-Container: Ruby

Install the Datadog Ruby SDK

Add the datadog gem to your Gemfile:

Gemfile

source 'https://rubygems.org'
gem 'datadog'

See Tracing Ruby applications for additional information on how to configure the SDK and enable auto instrumentation.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["rails", "server", "-b", "0.0.0.0"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "rails", "server", "-b", "0.0.0.0"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "rails", "server", "-b", "0.0.0.0"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends setting the environment variable DD_SOURCE=ruby to enable advanced Datadog log parsing.

To enable log-trace correlation, you need to include Datadog::Tracing.log_correlation in your log format. For example:

logger = Logger.new(STDOUT)
logger.formatter = proc do |severity, datetime, progname, msg|
  "[#{datetime}] #{severity}: [#{Datadog::Tracing.log_correlation}] #{msg}\n"
end

logger.info "Hello world!"

For more information, see Correlating Ruby Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

In-Container: PHP

Install the Datadog PHP SDK

Install the Datadog PHP SDK in your Dockerfile.

Dockerfile

RUN curl -LO https://github.com/DataDog/dd-trace-php/releases/latest/download/datadog-setup.php \
  && php datadog-setup.php --php-bin=all

When running the datadog-setup.php script, you can also enable Application Security and Profiling by using the --enable-appsec and --enable-profiling flags, respectively.

If you are using Alpine Linux, you need to install libgcc_s prior to running the installer:

apk add libgcc

For more information, see Tracing PHP applications.

Install serverless-init

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Add the following instructions and arguments to your Dockerfile.

Dockerfile

COPY --from=datadog/serverless-init:<YOUR_TAG> /datadog-init /app/datadog-init
ENTRYPOINT ["/app/datadog-init"]
CMD ["apache2-foreground"]

Datadog expects serverless-init to be the top-level application, with the rest of your app's command line passed in for serverless-init to execute.

If you already have an entrypoint defined inside your Dockerfile, you can instead modify the CMD argument.

CMD ["/app/datadog-init", "apache2-foreground"]

If you require your entrypoint to be instrumented as well, you can instead swap your entrypoint and CMD arguments.

ENTRYPOINT ["/app/datadog-init"]
CMD ["/your_entrypoint.sh", "apache2-foreground"]

As long as your command to run is passed as an argument to datadog-init, you receive full instrumentation.

Set up logs

To enable logging, set the environment variable DD_LOGS_ENABLED=true. This allows serverless-init to read logs from stdout and stderr.

Datadog also recommends setting the environment variables DD_LOGS_INJECTION=true and DD_SOURCE=php to enable advanced Datadog log parsing.

For more information, see Correlating PHP Logs and Traces.

Configure your application

After the container is built and pushed to your registry, set the required environment variables for the Datadog Agent:

  • DD_API_KEY: Your Datadog API key, used to send data to your Datadog account. For privacy and safety, configure this API key as a secret.
  • DD_SITE: Your Datadog site. For example, .

For more environment variables, see the Environment variables section on this page.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Sidecar: Python

Install the Datadog Python SDK

Add ddtrace to your requirements.txt or pyproject.toml. You can find the latest version on PyPI:

requirements.txt

ddtrace==<VERSION>

Alternatively, you can install the SDK in your Dockerfile:

Dockerfile

RUN pip install ddtrace

Then, wrap your start command with ddtrace-run:

Dockerfile

CMD ["ddtrace-run", "python", "app.py"]

For more information, see Tracing Python applications.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to the file set in DD_SERVERLESS_LOG_PATH. You can also set a custom format for log/trace correlation and other features. Datadog recommends setting the following environment variables:

  • ENV PYTHONUNBUFFERED=1: In your main container. Makes Python output appear immediately in container logs instead of being buffered.
  • ENV DD_LOGS_INJECTION=true: In your main container. Enable log/trace correlation for supported loggers.
  • DD_SOURCE=python: In your sidecar container. Enable advanced Datadog log parsing.

Then, update your logging library. For example, you can use Python's native logging library:

LOG_FILE = "/LogFiles/app.log"
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)

FORMAT = ('%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] '
        '[dd.service=%(dd.service)s dd.env=%(dd.env)s dd.version=%(dd.version)s dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s] '
        '- %(message)s')

logging.basicConfig(
    level=logging.INFO,
    format=FORMAT,
    handlers=[
        logging.FileHandler(LOG_FILE),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)
logger.level = logging.INFO

logger.info('Hello world!')

For more information, see Correlating Python Logs and Traces.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Enable profiling (preview)

To enable the Continuous Profiler, set the environment variable DD_PROFILING_ENABLED=true in your application container.

Datadog's Continuous Profiler is available in preview for Azure Container Apps.

Sidecar: Node.js

Install the Datadog Node.js SDK

In your main application, install the dd-trace package.

npm install dd-trace

Initialize the Node.js tracer with the NODE_OPTIONS environment variable:

Dockerfile

ENV NODE_OPTIONS="--require dd-trace/init"

For more information, see Tracing Node.js applications.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to the file set in DD_SERVERLESS_LOG_PATH. In Node.js, Datadog recommends writing logs in a JSON format. For example, you can use a third-party logging library such as winston:

const { createLogger, format, transports } = require('winston');

const LOG_FILE = "/LogFiles/app.log"

const logger = createLogger({
  level: 'info',
  exitOnError: false,
  format: format.json(),
  transports: [
    new transports.File({ filename: LOG_FILE }),
    new transports.Console()
  ],
});

logger.info('Hello world!');

Datadog recommends setting the environment variables DD_LOGS_INJECTION=true (in your main container) and DD_SOURCE=nodejs (in your sidecar container) to enable advanced Datadog log parsing.

For more information, see Correlating Node.js Logs and Traces.

Send custom metrics

To send custom metrics, view code examples. In serverless, only the distribution metric type is supported.

Enable profiling (preview)

To enable the Continuous Profiler, set the environment variable DD_PROFILING_ENABLED=true in your application container.

Datadog's Continuous Profiler is available in preview for Azure Container Apps.

Sidecar: Go

Install the Datadog Go SDK

In your main application, add the SDK from dd-trace-go.

go get github.com/DataDog/dd-trace-go/v2/ddtrace/tracer

Add the following to your application code to initialize the tracer:

tracer.Start()
defer tracer.Stop()

You can also add additional packages:

# Enable Profiling
go get github.com/DataDog/dd-trace-go/v2/profiler

# Patch /net/http
go get github.com/DataDog/dd-trace-go/contrib/net/http/v2

For more information, see Tracing Go Applications and the Tracer README.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to the file set in DD_SERVERLESS_LOG_PATH. In Go, Datadog recommends writing logs in a JSON format. For example, you can use a third-party logging library such as logrus:

const LOG_FILE = "/LogFiles/app.log"

os.MkdirAll(filepath.Dir(LOG_FILE), 0755)
logFile, err := os.OpenFile(LOG_FILE, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
defer logFile.Close()

logrus.SetOutput(logFile)
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.AddHook(&dd_logrus.DDContextLogHook{})

logrus.WithContext(ctx).Info("Hello World!")

Datadog recommends setting the environment variable DD_SOURCE=go in your sidecar container to enable advanced Datadog log parsing.

For more information, see Correlating Go Logs and Traces.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Sidecar: Java

Install the Datadog Java SDK

Add the Datadog Java SDK to your Dockerfile:

Dockerfile

ADD 'https://dtdg.co/latest-java-tracer' agent.jar
ENV JAVA_TOOL_OPTIONS="-javaagent:agent.jar"

Add the SDK artifacts.

<dependency>
  <groupId>com.datadoghq</groupId>
  <artifactId>dd-trace-api</artifactId>
  <version>DD_TRACE_JAVA_VERSION_HERE</version>
</dependency>
implementation 'com.datadoghq:dd-trace-api:DD_TRACE_JAVA_VERSION_HERE'

See dd-trace-java releases for the latest tracer version.

Add the @Trace annotation to any method you want to trace.

For more information, see Tracing Java Applications.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to the file set in DD_SERVERLESS_LOG_PATH. In Java, Datadog recommends writing logs in a JSON format. For example, you can use a third-party logging library such as Log4j 2:

private static final Logger logger = LogManager.getLogger(App.class);
logger.info("Hello World!");

resources/log4j2.xml

<Configuration>
  <Appenders>
    <Console name="Console"><JsonLayout compact="true" eventEol="true" properties="true"/></Console>
    <File name="FileAppender" fileName="/LogFiles/app.log">
      <JsonLayout compact="true" eventEol="true" properties="true"/>
    </File>
  </Appenders>
  <Loggers><Root level="info"><AppenderRef ref="FileAppender"/></Root></Loggers>
</Configuration>

Datadog recommends setting the environment variables DD_LOGS_INJECTION=true (in your main container) and DD_SOURCE=java (in your sidecar container) to enable advanced Datadog log parsing.

For more information, see Correlating Java Logs and Traces.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Sidecar: .NET

Install the Datadog .NET SDK

Install the Datadog .NET SDK in your Dockerfile.

Dockerfile

ARG TRACER_VERSION
RUN curl -L -s "https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm_${TRACER_VERSION}_amd64.deb" --output datadog-dotnet-apm.deb && \
   dpkg -i datadog-dotnet-apm.deb

Dockerfile

# For alpine use datadog-dotnet-apm-2.57.0-musl.tar.gz
ARG TRACER_VERSION
ADD https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm-${TRACER_VERSION}.tar.gz /tmp/datadog-dotnet-apm.tar.gz

RUN mkdir -p /dd_tracer/dotnet/ && tar -xzvf /tmp/datadog-dotnet-apm.tar.gz -C /dd_tracer/dotnet/ && rm /tmp/datadog-dotnet-apm.tar.gz

See the dd-trace-dotnet releases to view the latest tracer version.

For more information, see Tracing .NET applications.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to that file set in DD_SERVERLESS_LOG_PATH. In .NET, Datadog recommends writing logs in a JSON format. For example, you can use a third-party logging library such as Serilog:

using Serilog;

const string LOG_FILE = "/LogFiles/app.log";

builder.Host.UseSerilog((context, config) =>
{
    // Ensure the directory exists
    Directory.CreateDirectory(Path.GetDirectoryName(LOG_FILE)!);

    config.WriteTo.Console(new Serilog.Formatting.Json.JsonFormatter(renderMessage: true))
          .WriteTo.File(new Serilog.Formatting.Json.JsonFormatter(renderMessage: true), LOG_FILE);
});

logger.LogInformation("Hello World!");

Datadog recommends setting the environment variables DD_LOGS_INJECTION=true (in your main container) and DD_SOURCE=csharp (in your sidecar container) to enable advanced Datadog log parsing.

For more information, see Correlating .NET Logs and Traces.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Sidecar: Ruby

Install the Datadog Ruby SDK

Add the datadog gem to your Gemfile:

Gemfile

source 'https://rubygems.org'
gem 'datadog'

See Tracing Ruby applications for additional information on how to configure the SDK and enable auto instrumentation.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to the file set in DD_SERVERLESS_LOG_PATH. You can also set a custom format for log/trace correlation and other features. Datadog recommends setting the environment variable DD_SOURCE=ruby in your sidecar container to enable advanced Datadog log parsing.

Then, update your logging library. For example, you can use Ruby's native logger library:

LOG_FILE = "/LogFiles/app.log"
FileUtils.mkdir_p(File.dirname(LOG_FILE))

logger = Logger.new(LOG_FILE)
logger.formatter = proc do |severity, datetime, progname, msg|
  "[#{datetime}] #{severity}: [#{Datadog::Tracing.log_correlation}] #{msg}\n"
end

logger.info "Hello World!"

For more information, see Correlating Ruby Logs and Traces.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Sidecar: PHP

Install the Datadog PHP SDK

Install the Datadog PHP SDK in your Dockerfile.

Dockerfile

RUN curl -LO https://github.com/DataDog/dd-trace-php/releases/latest/download/datadog-setup.php \
  && php datadog-setup.php --php-bin=all

When running the datadog-setup.php script, you can also enable Application Security and Profiling by using the --enable-appsec and --enable-profiling flags, respectively.

If you are using Alpine Linux, you need to install libgcc_s prior to running the installer:

apk add libgcc

For more information, see Tracing PHP applications.

Install serverless-init as a sidecar

Datadog publishes new releases of the serverless-init container image to Google Container Registry, Amazon ECR Public Gallery, and Docker Hub:

hub.docker.comgcr.iopublic.ecr.aws
datadog/serverless-initgcr.io/datadoghq/serverless-initpublic.ecr.aws/datadog/serverless-init

Images are tagged based on semantic versioning, with each new version receiving three relevant tags:

  • 1, 1-alpine: use these to track the latest minor releases, without breaking changes
  • 1.x.x, 1.x.x-alpine: use these to pin to a precise version of the library
  • latest, latest-alpine: use these to follow the latest version release, which may include breaking changes

Locally

Install the Datadog CLI:

npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-container-app

Install the Azure CLI and authenticate with az login.

To set up the Datadog sidecar for your applications, configure the Datadog site and Datadog API key, and run the instrument command after your normal deployment:

export DD_SITE="<DATADOG_SITE>"
export DD_API_KEY="<DATADOG_API_KEY>"
datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

You can also instrument multiple applications using the full resource IDs:

datadog-ci container-app instrument \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-1>/providers/Microsoft.App/containerApps/<container-app-name-1>" \
  --resource-id "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name-2>/providers/Microsoft.App/containerApps/<container-app-name-2>"
Azure Cloud Shell

To use the Datadog CLI in Azure Cloud Shell, open a cloud shell, set your API key and site in the DD_API_KEY and DD_SITE environment variables, and use npx to run the CLI directly.

export DD_API_KEY=<DATADOG_API_KEY>
export DD_SITE=<DATADOG_SITE>
npx @datadog/datadog-ci container-app instrument -s <AZURE-SUBSCRIPTION-ID> -g <AZURE-RESOURCE-GROUP-NAME> -n <CONTAINER-APP-NAME>

Additional parameters can be found in the CLI documentation.

The Datadog Terraform module for Container Apps wraps the azurerm_container_app resource and automatically configures your Azure Container App for Datadog Serverless Monitoring by adding required environment variables and the serverless-init sidecar.

If you don't already have Terraform set up, install Terraform, create a new directory, and make a file called main.tf.

Then, add the following to your Terraform configuration, updating it as necessary based on your needs:

variable "datadog_api_key" {
  description = "Your Datadog API key"
  type        = string
  sensitive   = true
}

provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000000" // Replace with your subscription ID
}

resource "azurerm_container_app_environment" "my_env" {
    name                = "my-container-app-env" // Replace with your container app environment name
    resource_group_name = "my-resource-group"    // Replace with your resource group name
    location            = "eastus"
}

module "my_container_app" {
  source  = "DataDog/container-app-datadog/azurerm"
  version = "~> 1.0"

  name                         = "my-container-app" // Replace with your container app name
  resource_group_name          = "my-resource-group" // Replace with your resource group name
  container_app_environment_id = azurerm_container_app_environment.my_env.id

  datadog_api_key = var.datadog_api_key
  datadog_site    = "datadoghq.com" // Replace with your Datadog site
  datadog_service = "my-service"    // Replace with your service name
  datadog_env     = "dev"           // Replace with your environment (e.g. prod, staging, dev)
  datadog_version = "0.1.0"         // Replace with your application version

  revision_mode         = "Single"
  workload_profile_name = "Consumption"
  ingress = {
    external_enabled = true
    target_port      = 8080
    traffic_weight = [{
      percentage      = 100
      latest_revision = true
    }]
  }
  template = {
    container = [{
      cpu    = 0.5
      memory = "1Gi"
      image  = "docker.io/your-docker-image:latest" // Replace with your Docker image
      name   = "main"
    }]
  }
}

Finally, run terraform apply, and follow any prompts.

The Datadog Container App module only deploys the Container App resource, so you need to build and push your container separately.

See the Environment variables section for more information on the configuration options available through the env.

Make sure the container port for the main container matches the one exposed in your Dockerfile/service.

If you haven't already, initialize your Terraform project:

terraform init

To deploy your app, run:

terraform apply

Update your existing Container App bicep to include the necessary Datadog App Settings and sidecar, as follows:

@secure()
param datadogApiKey string
param datadogSite string
param service string = 'my-service'
param env string = 'dev'
param version string = '0.0.0'

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  // ...
  properties: {
    template: {
      volumes: [
        {
          name: 'shared-volume'
          storageType: 'EmptyDir'
        }
        // Additional volumes
      ]
      containers: [
        {
          name: 'main'
          image: 'index.docker.io/your/image:tag' // Replace with your Application Image
          resources: {
            cpu: 1
            memory: '2Gi'
          }
          env: [
            { name: 'DD_ENV', value: env }
            { name: 'DD_SERVICE', value: name }
            { name: 'DD_VERSION', value: version }
            { name: 'DD_LOGS_INJECTION', value: 'true' }
            // Additional tracing/application env vars
          ]
          volumeMounts: [
            { volumeName: 'shared-volume', mountPath: '/shared-volume' }
            // Additional volume mounts
          ]
        }
        {
          name: 'datadog-sidecar'
          image: 'index.docker.io/datadog/serverless-init:latest'
          resources: {
            cpu: '0.5'
            memory: '1Gi'
          }
          env: [
            { name: 'DD_AZURE_SUBSCRIPTION_ID', value: subscription().subscriptionId }
            { name: 'DD_AZURE_RESOURCE_GROUP', value: resourceGroup().name }
            { name: 'DD_API_KEY', value: datadogApiKey }
            { name: 'DD_SITE', value: datadogSite }
            { name: 'DD_SERVICE', value: service }
            { name: 'DD_ENV', value: env }
            { name: 'DD_VERSION', value: version }
            // set this to wherever you write logs in the shared volume:
            { name: 'DD_SERVERLESS_LOG_PATH', value: '/shared-volume/logs/app.log' }
          ]
          volumeMounts: [{ volumeName: 'shared-volume', mountPath: '/shared-volume' }]
        }
      ]
      scale: { minReplicas: 1, maxReplicas: 1, rules: [] }
    }
  }
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Update your existing Container App ARM Template to include the necessary Datadog App Settings and sidecar, as follows:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "datadogApiKey": {
      "type": "securestring"
    },
    "datadogSite": {
      "type": "string"
    },
    "service": {
      "type": "string",
      "defaultValue": "my-service"
    },
    "env": {
      "type": "string",
      "defaultValue": "dev"
    },
    "version": {
      "type": "string",
      "defaultValue": "0.0.0"
    }
  },
  "resources": [
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      // ...
      "properties": {
        "template": {
          "volumes": [
            {
              "name": "shared-volume",
              "storageType": "EmptyDir"
            }
            // Additional volumes
          ],
          "containers": [
            {
              "name": "main",
              "image": "index.docker.io/your/image:tag", // Replace with your Application Image
              "resources": {
                "cpu": 1,
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                // Additional tracing/application env vars
                {
                  "name": "DD_LOGS_INJECTION",
                  "value": "true"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
                // Additional volume mounts
              ]
            },
            {
              "name": "datadog-sidecar",
              "image": "index.docker.io/datadog/serverless-init:latest",
              "resources": {
                "cpu": "0.5",
                "memory": "1Gi"
              },
              "env": [
                {
                  "name": "DD_AZURE_SUBSCRIPTION_ID",
                  "value": "[subscription().subscriptionId]"
                },
                {
                  "name": "DD_AZURE_RESOURCE_GROUP",
                  "value": "[resourceGroup().name]"
                },
                {
                  "name": "DD_API_KEY",
                  "value": "[parameters('datadogApiKey')]"
                },
                {
                  "name": "DD_SITE",
                  "value": "[parameters('datadogSite')]"
                },
                {
                  "name": "DD_SERVICE",
                  "value": "[parameters('service')]"
                },
                {
                  "name": "DD_ENV",
                  "value": "[parameters('env')]"
                },
                {
                  "name": "DD_VERSION",
                  "value": "[parameters('version')]"
                },
                {
                  "name": "DD_SERVERLESS_LOG_PATH",
                  // set this to wherever you write logs in the shared volume:
                  "value": "/shared-volume/logs/app.log"
                }
              ],
              "volumeMounts": [
                {
                  "volumeName": "shared-volume",
                  "mountPath": "/shared-volume"
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1,
            "rules": []
          }
        }
      }
    }
  ]
}

Redeploy your updated template:

az deployment group create --resource-group <RESOURCE GROUP> --template-file <TEMPLATE FILE>

See the Manual tab for descriptions of all environment variables.

Application environment variables

Because Azure Container Apps is built on Kubernetes, you cannot share environment variables between containers.

NameDescription
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.

Sidecar container

  1. In the Azure Portal, navigate to Application > Revisions and replicas. Select Create new revision.
  2. On the Container tab, under Container image, select Add. Choose App container.
  3. In the Add a container form, provide the following:
    • Name: datadog
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: datadog/serverless-init:<YOUR_TAG>
    • Define your container resource allocation based on your usage.
  4. Add a volume mount using replica-scoped storage. Use type "Ephemeral storage" when creating your volume. Make sure the name and mount path match the mount you configured in the application container.
  5. Set the environment variables in the following table:
Sidecar environment variables
NameDescription
DD_AZURE_SUBSCRIPTION_IDRequired. Your Azure subscription ID.
DD_AZURE_RESOURCE_GROUPRequired. Your Azure resource group.
DD_API_KEYRequired. Your Datadog API key.
DD_SITEYour Datadog site. For example, datadoghq.com.
DD_SERVICEHow you want to tag your service. For example, sidecar-azure.
DD_ENVHow you want to tag your env. For example, prod.
DD_VERSIONHow you want to tag your application version.
DD_SERVERLESS_LOG_PATHIf using the agent for log collection, where you write your logs. For example, /LogFiles/*.log. This must match the logging path set up in your application container.

Logging

If using the Datadog Agent for log collection, add a volume mount to the sidecar container and your application containers using replica-scoped storage. Use type Ephemeral storage when creating your volume. The examples on this page use the volume name logs and the mount path /LogFiles.

Adding a volume mount to a container in Azure

Set up logs

In the previous step, you created a shared volume. In this step, configure your logging library to write logs to the file set in DD_SERVERLESS_LOG_PATH. For example:

const LOG_FILE = "/LogFiles/app.log";

function logInfo($message) {
    Log::build([
        'driver' => 'single',
        'path' => LOG_FILE,
    ])->info($message);
}

logInfo('Hello World!');

Datadog recommends setting the environment variables DD_LOGS_INJECTION=true (in your main container) and DD_SOURCE=php (in your sidecar container) to enable advanced Datadog log parsing.

For more information, see Correlating PHP Logs and Traces.

Send custom metrics

To send custom metrics, install the DogStatsD client and view code examples. In serverless, only the distribution metric type is supported.

Environment variables

VariableDescription
DD_API_KEYDatadog API key - Required
DD_SITEDatadog site - Required
DD_SERVICEDatadog Service name. Required
DD_AZURE_SUBSCRIPTION_IDAzure Subscription ID. Required
DD_AZURE_RESOURCE_GROUPAzure Resource Group name. Required
DD_LOGS_ENABLEDWhen true, send logs (stdout and stderr) to Datadog. Defaults to false.
DD_LOGS_INJECTIONWhen true, enrich all logs with trace data for supported loggers. See Correlate Logs and Traces for more information.
DD_VERSIONSee Unified Service Tagging.
DD_ENVSee Unified Service Tagging.
DD_SOURCESet the log source to enable a Log Pipeline for advanced parsing. To automatically apply language-specific parsing rules, set it to your application language (python, nodejs, go, java, csharp, ruby, or php), or use your custom pipeline. Defaults to containerapp.
DD_TAGSAdd custom tags to your logs, metrics, and traces. Tags should be comma separated in key/value format (for example: key1:value1,key2:value2).

For Java, also set JAVA_TOOL_OPTIONS (Required for tracing) to the path to the Datadog Java agent. For example, -javaagent:/path/to/dd-java-agent.jar.

VariableDescriptionContainer
DD_API_KEYDatadog API key - RequiredSidecar container
DD_SITEDatadog site - RequiredSidecar container
DD_SERVICEDatadog Service name. RequiredBoth containers
DD_AZURE_SUBSCRIPTION_IDAzure Subscription ID. RequiredSidecar container
DD_AZURE_RESOURCE_GROUPAzure Resource Group name. RequiredSidecar container
DD_SERVERLESS_LOG_PATHThe path where the sidecar should tail logs from. Recommended to set to /shared-volume/logs/app.log.Sidecar container
DD_LOGS_INJECTIONWhen true, enrich all logs with trace data for supported loggers. See Correlate Logs and Traces for more information.Application container
DD_VERSIONSee Unified Service Tagging.Both containers
DD_ENVSee Unified Service Tagging.Both containers
DD_SOURCESet the log source to enable a Log Pipeline for advanced parsing. To automatically apply language-specific parsing rules, set it to your application language (python, nodejs, go, java, csharp, ruby, or php), or use your custom pipeline. Defaults to containerapp.Sidecar container
DD_TAGSAdd custom tags to your logs, metrics, and traces. Tags should be comma separated in key/value format (for example: key1:value1,key2:value2).Sidecar container

For Java, also set JAVA_TOOL_OPTIONS (Required for tracing) in the application container to the path to the Datadog Java agent. For example, -javaagent:/path/to/dd-java-agent.jar.

Do not set the following environment variables in your serverless environment. They should only be set in non-serverless environments.

  • DD_AGENT_HOST
  • DD_TRACE_AGENT_URL

Troubleshooting

This integration depends on your runtime having a full SSL implementation. If you are using a slim image, you may need to add the following command to your Dockerfile to include certificates:

RUN apt-get update && apt-get install -y ca-certificates

To have your services appear in the Catalog, you must set the DD_SERVICE, DD_VERSION, and DD_ENV environment variables.

If you are missing logs or traces during container shutdown, specify a container start up order to make your main container depend on the sidecar container.

Further reading