Continuous Profiling
Continuous profiling captures real-time performance data from your applications - CPU usage, memory allocations, wall-clock time, and more. Moneat ingests profiles from both the Sentry SDK and the Datadog Agent, so you can use whichever fits your stack.
Enable profiling with the Datadog Agent
datadog.yaml is the main configuration file for the Datadog Agent. Its default location depends on your platform:
| Platform | Path |
|---|---|
| Linux | /etc/datadog-agent/datadog.yaml |
| macOS | /opt/datadog-agent/etc/datadog.yaml |
| Windows | C:\ProgramData\Datadog\datadog.yaml |
| Docker | Pass configuration via environment variables (see below) |
Add the following to your datadog.yaml:
# datadog.yaml
apm_config:
enabled: true
profiling_dd_url: "__MONEAT_BACKEND_URL__/api/v2/profile?api_key=<YOUR_MONEAT_AGENT_KEY>"
telemetry:
dd_url: "__MONEAT_BACKEND_URL__/dd/telemetry/proxy"
# Point to your Moneat instance
dd_url: "__MONEAT_BACKEND_URL__/dd"If you're running the Agent in Docker, pass the profiling endpoint as an environment variable. The EPForwarder redirects require a datadog.yaml file (see Agent Setup):
docker run -e DD_APM_ENABLED=true \
-e DD_DD_URL=__MONEAT_BACKEND_URL__/dd \
-e DD_APM_CONFIG_PROFILING_DD_URL=__MONEAT_BACKEND_URL__/api/v2/profile?api_key=<YOUR_MONEAT_AGENT_KEY> \
datadog/agent:latestThen restart the Datadog Agent:
# Linux / macOS (systemd)
sudo systemctl restart datadog-agent
# Docker
docker restart dd-agentOnce the Agent is running, instrument your applications as described below.
How profiling works
Configuring datadog.yaml tells the Agent to accept and forward profiles - it does not automatically profile every process on the host. Each application you want to profile must be individually instrumented with the Datadog language-specific profiler, which handles the actual data collection and sends it to the Agent.
The Agent then forwards those profiles to Moneat.
Instrumenting your application
Each profiler sends data to the Agent at localhost:8126 by default. In Docker environments, set DD_AGENT_HOST to the Agent container's hostname instead.
Java
Standalone:
Download the Datadog Java agent JAR:
wget -O dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'Attach it at JVM startup:
DD_SERVICE=my-java-app \
DD_ENV=production \
DD_PROFILING_ENABLED=true \
java -javaagent:/path/to/dd-java-agent.jar -jar my-app.jarDocker:
Add the agent JAR to your image and set DD_AGENT_HOST to reach the Agent container:
FROM eclipse-temurin:21-jre
RUN apt-get update && apt-get install -y wget && \
wget -O /dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'
COPY target/my-app.jar /app.jar
ENTRYPOINT ["java", "-javaagent:/dd-java-agent.jar", "-jar", "/app.jar"]Then in your docker-compose.yaml:
services:
datadog-agent:
image: datadog/agent:latest
environment:
- DD_APM_ENABLED=true
- DD_APM_NON_LOCAL_TRAFFIC=true
- DD_DD_URL=__MONEAT_BACKEND_URL__/dd
- DD_APM_CONFIG_PROFILING_DD_URL=__MONEAT_BACKEND_URL__/api/v2/profile?api_key=<YOUR_MONEAT_AGENT_KEY>
- DD_API_KEY=<YOUR_MONEAT_AGENT_KEY>
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /proc/:/host/proc/:ro
- /sys/fs/cgroup/:/host/sys/fs/cgroup:ro
pid: host
my-java-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-java-app
- DD_ENV=production
- DD_PROFILING_ENABLED=true
# DD_API_KEY must be a 32-character hex string for the Java profiler's
# format check. It is only validated locally - the agent uses its own key.
- DD_API_KEY=00000000000000000000000000000000
depends_on:
- datadog-agentDD_AGENT_HOST=datadog-agent tells the Java profiler to send profiles to the Agent container rather than localhost.
Python
Standalone:
pip install ddtrace
DD_SERVICE=my-python-app \
DD_ENV=production \
DD_PROFILING_ENABLED=true \
ddtrace-run python my_app.pyDocker:
FROM python:3.12-slim
RUN pip install ddtrace
COPY . /app
WORKDIR /app
CMD ["ddtrace-run", "python", "my_app.py"]# docker-compose.yaml
services:
my-python-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-python-app
- DD_ENV=production
- DD_PROFILING_ENABLED=trueNode.js
Standalone:
npm install dd-traceInitialize at the very top of your entry file, before any other imports:
// Must be the first line
require('dd-trace').init({
service: 'my-node-app',
env: 'production',
profiling: true,
});Docker:
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "server.js"]# docker-compose.yaml
services:
my-node-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-node-app
- DD_ENV=production
- DD_PROFILING_ENABLED=trueReact runs in the browser, not on a server, so the Datadog Agent cannot profile it - there is no process for the Agent to attach to. If you have a Node.js backend serving your React app, you can profile that using the setup above.
For profiling browser-side JavaScript (React, Vue, Angular, etc.), use the Sentry SDK instead - see the Profiling with the Sentry SDK section below.
Go
Add the profiler to your application:
go get gopkg.in/DataDog/dd-trace-go.v1/profilerpackage main
import (
"log"
"time"
"gopkg.in/DataDog/dd-trace-go.v1/profiler"
)
func main() {
err := profiler.Start(
profiler.WithService("my-go-app"),
profiler.WithEnv("production"),
profiler.WithProfileTypes(
profiler.CPUProfile,
profiler.HeapProfile,
profiler.GoroutineProfile,
),
)
if err != nil {
log.Fatal(err)
}
defer profiler.Stop()
// your application code
}Docker: Set DD_AGENT_HOST in your container environment (no JAR or binary download needed - the profiler is linked into your binary):
# docker-compose.yaml
services:
my-go-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-go-app
- DD_ENV=productionRuby
Add the gem to your Gemfile:
gem 'datadog'Then enable profiling in your app initializer:
require 'datadog/profiling/preload'
Datadog.configure do |c|
c.service = 'my-ruby-app'
c.env = 'production'
c.profiling.enabled = true
endDocker:
FROM ruby:3.3-slim
WORKDIR /app
COPY Gemfile* ./
RUN bundle install
COPY . .
CMD ["ruby", "app.rb"]# docker-compose.yaml
services:
my-ruby-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-ruby-app
- DD_ENV=production
- DD_PROFILING_ENABLED=true.NET
Install the Datadog .NET tracer. On Linux:
wget https://github.com/DataDog/dd-trace-dotnet/releases/latest/download/datadog-dotnet-apm_amd64.deb
dpkg -i datadog-dotnet-apm_amd64.deb
/opt/datadog/createLogPath.shSet environment variables before running your app:
export CORECLR_ENABLE_PROFILING=1
export CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8}
export CORECLR_PROFILER_PATH=/opt/datadog/Datadog.Trace.ClrProfiler.Native.so
export DD_DOTNET_TRACER_HOME=/opt/datadog
export DD_SERVICE=my-dotnet-app
export DD_ENV=production
export DD_PROFILING_ENABLED=true
dotnet my-app.dllDocker:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y wget && \
wget https://github.com/DataDog/dd-trace-dotnet/releases/latest/download/datadog-dotnet-apm_amd64.deb && \
dpkg -i datadog-dotnet-apm_amd64.deb && \
/opt/datadog/createLogPath.sh
COPY /app/publish /app
WORKDIR /app
ENV CORECLR_ENABLE_PROFILING=1
ENV CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8}
ENV CORECLR_PROFILER_PATH=/opt/datadog/Datadog.Trace.ClrProfiler.Native.so
ENV DD_DOTNET_TRACER_HOME=/opt/datadog
ENTRYPOINT ["dotnet", "my-app.dll"]# docker-compose.yaml
services:
my-dotnet-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-dotnet-app
- DD_ENV=production
- DD_PROFILING_ENABLED=truePHP
Install the Datadog PHP tracer extension:
wget https://github.com/DataDog/dd-trace-php/releases/latest/download/datadog-setup.php
php datadog-setup.php --php-bin=all --enable-profilingSet the environment before starting PHP-FPM or your web server:
DD_SERVICE=my-php-app \
DD_ENV=production \
DD_PROFILING_ENABLED=true \
php-fpmDocker:
FROM php:8.3-fpm
RUN apt-get update && apt-get install -y wget && \
wget https://github.com/DataDog/dd-trace-php/releases/latest/download/datadog-setup.php && \
php datadog-setup.php --php-bin=all --enable-profiling
CMD ["php-fpm"]# docker-compose.yaml
services:
my-php-app:
build: .
environment:
- DD_AGENT_HOST=datadog-agent
- DD_SERVICE=my-php-app
- DD_ENV=production
- DD_PROFILING_ENABLED=trueSupported profile types
Moneat supports the following profile types from the Datadog Agent:
| Profile Type | Description |
|---|---|
| cpu | CPU time consumed by your application |
| wall | Wall-clock time (real elapsed time) |
| heap | Current heap memory usage |
| alloc | Memory allocation rate |
| goroutine | Active goroutines (Go applications) |
| mutex | Mutex contention and wait times |
| block | Blocking operations and wait times |
Viewing profiles
Navigate to Profiles in the dashboard and select the Datadog Agent tab.
Filtering
- Service - Search by service name to focus on a specific application
- Type - Filter by profile type (CPU, heap, wall, etc.)
Profile details
Each profile entry shows:
- Service - The application or service that generated the profile
- Type - The kind of profile (CPU, heap, wall, etc.)
- Environment - The deployment environment (production, staging)
- Host - The host where the profile was collected
- Duration - How long the profiling session lasted
- Size - The profile data size
- Time - When the profile was captured
Click on any profile to view its detailed flamegraph and drill into specific functions.
Profiling with the Sentry SDK
You can also collect profiles using the Sentry SDK. For Node.js, use @sentry/node and the
matching @sentry/profiling-node package at version 10.70.0 or later, with both packages at
exactly the same version. Configure profileSessionSampleRate and
profileLifecycle: "trace". See the Profiles → Sentry SDK tab in the dashboard for
platform-specific setup instructions.
JavaScript / TypeScript:
import * as Sentry from "@sentry/node";
import { nodeProfilingIntegration } from "@sentry/profiling-node";
Sentry.init({
dsn: "YOUR_DSN_HERE",
integrations: [nodeProfilingIntegration()],
tracesSampleRate: 1.0,
profileSessionSampleRate: 1.0,
profileLifecycle: "trace",
});Python:
import sentry_sdk
sentry_sdk.init(
dsn="YOUR_DSN_HERE",
traces_sample_rate=1.0,
profiles_sample_rate=1.0,
)