C++
This guide explains how to instrument a C++ application in Motadata APM for trace ingestion.
C++ instrumentation is supported only through the Linux agent, and can be configured for the following deployment types:
- Host/VM
- Docker
Prerequisites
Before instrumenting a C++ application, ensure the following prerequisites are met:
- The Motadata Agent must be installed and running on the Linux machine where the application is deployed.
- The OTEL collector must also be running as part of the Motadata Agent.
- To verify the agent status, run:
service motadata status
- C++ instrumentation is supported only for Linux.
- CMake must be 3.16 or higher.
- Compiler must be GCC 5+ or Clang 6+.
protocmust be 3.12 or higher.pkg-config,curl,git, and required build dependencies must be available.- The OTEL C++ SDK version used in this setup is v1.23.0.
- The Motadata wrapper library used for instrumentation is
motadata-apm-cpp-instrumentation. - The application must already be working and able to start without errors before instrumentation is added.
- You may need root/sudo access for dependency installation, SDK installation, and runtime setup.
Configuration Steps
Step1: Register the Application Service in Motadata APM
Go to Menu > Settings > APM > Application Registration. Click Application Registration to register a new application.
From the registration screen, select the required instrumentation type.
- Host/VM
- Docker
Step2: Configure C++ Instrumentation on Linux Host/VM
C++ Trace Configuration
| Field | Description |
|---|---|
| Select Agent | Select the Linux Host/VM where this C++ application is running. |
| Select Language | Select C++ from the language icons. |
| Service Name | Provide a unique and meaningful service name, such as order-service, inventory-engine, or pricing-service. |
| Setup Instructions | Please refer the below section for the steps to instrument a C++ application. |
| Service Attributes (Tags) | Add key-value tags to your application for better filtering and organizing data in Explorer. Attribute key names must be lowercase. |
| Add Custom Parameters | Allows you to define custom parameters for advanced use cases. |
Click Apply Configuration to complete the registration.
Providing these details displays you can instrument your application. Execute the setup script and restart the application to start collecting Traces.
Setup Instructions
1. Verify Your Machine Has the Required Tools
Run the following commands and confirm that each one returns a valid version:
| Command to run | What to expect |
|---|---|
cmake --version | Must show version 3.16 or higher. CMake is the build system. |
g++ --version | Must show GCC 5 or higher. This is the C++ compiler. Alternatively, you can use clang++ --version and it must show Clang 6 or higher. |
protoc --version | Must show 3.12 or higher. This is the Protobuf compiler, required by the Motadata instrumentation SDK to serialize spans. |
curl --version | Any version is acceptable. libcurl is used to send traces over HTTP. |
git --version | Any version is acceptable. Git is used to download the Motadata instrumentation SDK source code. |
pkg-config --version | Any version is acceptable. pkg-config helps CMake locate installed libraries. |
If any dependency is missing, install it.
For Ubuntu or Debian:
sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
git \
pkg-config \
libcurl4-openssl-dev \
libssl-dev \
libprotobuf-dev \
protobuf-compiler
For RHEL, CentOS, or Amazon Linux:
sudo yum groupinstall "Development Tools"
sudo yum install -y \
cmake3 git pkg-config \
libcurl-devel openssl-devel \
protobuf-devel protobuf-compiler
If cmake3 is installed instead of cmake, create the alias:
sudo ln -s /usr/bin/cmake3 /usr/bin/cmake
2. Install and Build Instrumentation C++ SDK
cd /opt
sudo git clone --depth 1 --branch v1.23.0 \
https://github.com/open-telemetry/opentelemetry-cpp.git
cd /opt/opentelemetry-cpp
sudo git submodule update --init --recursive
Create the build directory and configure the build:
cd /opt/opentelemetry-cpp
mkdir build
cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=14 \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DWITH_OTLP_HTTP=ON \
-DWITH_OTLP_GRPC=OFF \
-DBUILD_TESTING=OFF \
-DWITH_EXAMPLES=OFF \
-DCMAKE_INSTALL_PREFIX=/usr/local
| CMake Flag | What it does and why |
|---|---|
-DCMAKE_BUILD_TYPE=Release | Compile in Release mode for an optimized and smaller binary. Do not use Debug here. |
-DCMAKE_CXX_STANDARD=14 | Use C++14 or higher. The motadata-apm-cpp-instrumentation library supports C++14 and above. |
-DCMAKE_POSITION_INDEPENDENT_CODE=ON | Required for static libraries to link correctly into other programs. |
-DWITH_OTLP_HTTP=ON | Enables the HTTP exporter. This is how spans are sent to port 4318, so it is required. |
-DWITH_OTLP_GRPC=OFF | Disables the gRPC exporter. This keeps the build simpler and it is not required here. |
-DBUILD_TESTING=OFF | Skips compiling the SDK test suite, which saves around 10 minutes of build time. |
-DWITH_EXAMPLES=OFF | Skips compiling SDK examples because they are not needed. |
-DCMAKE_INSTALL_PREFIX=/usr/local | Installs the compiled SDK headers and libraries into /usr/local, which is a standard system path. |
Compile the SDK
cmake --build . -j$(nproc)
sudo cmake --install .
Verify the installation:
ls /usr/local/include/opentelemetry/
Expected output: folders named trace/, sdk/, exporters/, common/, etc.
ls /usr/local/lib/ | grep opentelemetry | head -5
Expected output: several files named libopentelemetry_*.a
3. Add the Motadata Wrapper to the Project
Clone the wrapper repository into the project root so that the directory structure contains motadata-cpp/ alongside your project files.
Expected structure:
your-project/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ └── other_files.cpp
└── motadata-cpp/
├── include/
│ └── motadata.h
├── src/
│ └── motadata.cpp
└── CMakeLists.txt
4. Update CMakeLists.txt
Add the Motadata wrapper as a subdirectory and link the required libraries.
cmake_minimum_required(VERSION 3.16)
project(YourProjectName LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(motadata-cpp)
add_executable(your_app
src/main.cpp
src/other_files.cpp
)
target_link_libraries(your_app PRIVATE
motadata
curl
pthread
)
| Addition | Why it is needed |
|---|---|
add_subdirectory(motadata-cpp) | Tells CMake to enter the motadata-cpp/ folder and process its CMakeLists.txt. This automatically builds the instrumentation library as part of your project build, so no separate build step is needed. |
motadata | Links the compiled wrapper library into your application. After this, your code can call motadata:: functions. |
curl | Links libcurl, which is the HTTP client library. The wrapper uses curl internally to send spans to the Collector. This is a standard system library already installed on the machine. |
pthread | Links the POSIX threads library. It is required on Linux for multithreaded execution and is a standard system library. |
5. Verify the Library Compiles
Before writing any instrumentation code, confirm the library builds correctly with your project:
cd your-project
mkdir build
cd build
Configure your project
cmake .. -DCMAKE_BUILD_TYPE=Release
In the CMake output you should see a line like:
-- motadata configuration:
-- Version : 1.0.0
-- C++ Standard : 17
Compile everything
make -j$(nproc)
6. Include the Motadata Header
In every .cpp file where spans will be created, add:
#include "motadata.h"
Initialize Telemetry
Initialize telemetry once, at the top of main():
#include "motadata.h"
#include <iostream>
int main() {
motadata::TelemetryConfig cfg;
cfg.service_name = "your-service-name";
cfg.service_version = "1.0.0";
cfg.collector_url = "http://localhost:4318";
cfg.debug_print_to_console = true;
if (!motadata::initTelemetry(cfg)) {
std::cerr << "[telemetry] Warning: init failed, continuing without tracing\n";
}
runYourApplication();
motadata::shutdown();
return 0;
}
| Config Field | Explanation |
|---|---|
service_name | Defines how your service appears in the observability UI. Use a short, lowercase, descriptive name. Example: order-service, auth-api, data-processor. |
service_version | Specifies your application version string. This is useful for identifying which release introduced a problem. Example: 2.1.0, release-47. |
collector_url | Specifies the URL of the Motadata Instrumentation Collector. The default value is http://localhost:4318. Change this only if the Collector is running on a different host or port. |
debug_print_to_console | When set to true, every span is also printed to stdout in a human-readable format. This is useful during development and troubleshooting. Set it to false in production because it adds unnecessary log noise. |
7. Create Spans
Basic span example:
void processOrder(const std::string& order_id, double total) {
auto span = motadata::startSpan("processOrder");
span->setAttr("order.id", order_id);
span->setAttr("order.total", total);
span->setAttr("order.currency", "USD");
validateOrder(order_id);
chargePayment(order_id, total);
sendConfirmation(order_id);
span->setOk();
span->end();
}
Error handling example:
void chargePaymentGateway(const std::string& order_id, double amount) {
auto span = motadata::startSpan("chargePaymentGateway");
span->setAttr("order.id", order_id);
span->setAttr("amount", amount);
try {
callGatewayAPI(order_id, amount);
span->setOk();
span->end();
} catch (const std::exception& e) {
span->recordException(e);
span->end();
throw;
}
}
Nested spans
void processOrder() {
auto span = motadata::startSpan("processOrder");
fetchOrderFromDatabase();
chargePaymentGateway();
sendConfirmationEmail();
span->setOk();
span->end();
}
void fetchOrderFromDatabase() {
auto span = motadata::startSpan("fetchOrderFromDatabase");
span->setAttr("db.system", "postgresql");
span->setAttr("db.name", "orders");
span->setAttr("db.statement", "SELECT * FROM orders WHERE id = ?");
span->setAttr("db.rows_returned", 1);
span->setOk();
span->end();
}
Cross-thread example:
void processOrdersInBackground() {
auto parent = motadata::startSpan("processOrdersInBackground");
parent->setAttr("batch.size", 100);
auto ctx = parent->getContext();
std::thread worker([ctx]() {
auto child = motadata::startSpan("WorkerThread::ProcessBatch", ctx);
child->setAttr("thread.type", "batch-worker");
child->setOk();
child->end();
});
worker.join();
parent->setOk();
parent->end();
}
HTTP propagation example:
void callInventoryService(const std::string& sku) {
auto span = motadata::startSpan("callInventoryService");
span->setAttr("http.method", "GET");
span->setAttr("http.url", "http://inventory-service/api/stock/" + sku);
motadata::HttpHeaders headers;
headers["Content-Type"] = "application/json";
motadata::injectHeaders(headers);
span->setAttr("http.status_code", 200);
span->setOk();
span->end();
}
8. Build the Application
cd your-project
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
9. Run and Verify
Run the application:
./your_app
If debug_print_to_console = true, spans are printed to the terminal during execution.
You can also verify collector connectivity independently:
curl -X POST http://localhost:4318/v1/traces \
-H "Content-Type: application/json" \
-d '{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"connectivity-test"}}]},"scopeSpans":[{"spans":[{"traceId":"00000000000000000000000000000001","spanId":"0000000000000001","name":"test-span","kind":1,"startTimeUnixNano":"1677000000000000000","endTimeUnixNano":"1677000001000000000","status":{"code":1}}]}]}]}'
Expected response:
{}
Important Rules
| Rule | Explanation |
|---|---|
Always call span->end() | Every startSpan() must have a matching end() on every code path. |
Always call motadata::shutdown() before exit | Buffered spans are flushed during shutdown. |
Call motadata::initTelemetry() only once | Initialize telemetry once, at the top of main(). |
| Never terminate the application if telemetry initialization fails | Application flow must continue even when tracing is unavailable. |
| Never share span objects across threads | Use span->getContext() and create a new child span in the target thread. |
Step2: Configure C++ Instrumentation on Linux Docker
C++ Trace Configuration
| Field | Description |
|---|---|
| Select Agent | Select the Linux Docker host where this C++ application is running. |
| Language | Select C++ from the language icons. |
| Service Name | Provide a unique and meaningful service name, such as cpp-docker-app, inventory-api, or pricing-engine. |
| Image Name | Specify the Docker image name where your application is running. (e.g nginx:latest) |
| Setup Instructions | Please refer the below section for the steps to instrument a C++ application. |
| Service Attributes (Tags) | Add key-value tags to your application for better filtering and organizing data in Explorer. Attribute key names must be lowercase. |
| Add Custom Parameters | Allows you to define custom parameters for advanced use cases. |
| Setup Command | Start collecting Traces by running your container as shown command. |
Click Apply Configuration to complete the registration.
Providing these details displays you can instrument your application. Execute the setup script and restart the application to start collecting Traces.
Setup Instructions
1. Environment Requirements
| Item | Requirement |
|---|---|
| CMake | 3.16 or higher. You can check it using cmake --version |
| Compiler | GCC 5 or higher. You can check it using g++ --version |
| Protobuf Compiler | 3.12 or higher. You can check it using protoc --version |
| Collector Endpoint | http://host.docker.internal:4318 |
| Docker Run Option | --add-host=host.docker.internal:host-gateway |
All dependencies are installed automatically during Docker image build.
2. Project Structure
YourApp/
├── Dockerfile
├── .dockerignore
├── CMakeLists.txt
├── main.cpp
└── motadata-cpp/
├── include/
│ └── motadata.h
├── src/
│ └── motadata.cpp
└── CMakeLists.txt
Compiled C++ libraries depend on the operating system, compiler version, and system libraries of the machine they were built on. To ensure compatibility with the actual runtime environment, the C++ instrumentation SDK is compiled inside the Docker image during build instead of using a prebuilt binary.
So, approximately 10–15 minutes additional time will be taken when build for the first time, as the C++ SDK is compiled inside the container during the image build.
3. Update Dockerfile
The following shows exactly where to add each Motadata block inside your existing Dockerfile, using a typical single-stage and multi-stage Dockerfile as reference.
Lines marked with # ── MOTADATA ADD ── are the additions. All other lines represent your existing Dockerfile leave them untouched. Also, read the comments carefully in the below command snippets and work accordingly.
- Single-Stage Dockerfile
- Multi-Stage Dockerfile
Builder Stage
Your dockerfile may have the below section, which should be unchanged:
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y cmake g++ make && \
rm -rf /var/lib/apt/lists/*
Add the below mentioned snippets, under your existing apt-get block.
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
pkg-config \
libcurl4-openssl-dev \
libssl-dev \
libprotobuf-dev \
protobuf-compiler \
&& rm -rf /var/lib/apt/lists/*
RUN git clone --depth 1 --branch v1.23.0 \
https://github.com/open-telemetry/opentelemetry-cpp.git \
/opt/opentelemetry-cpp \
&& cd /opt/opentelemetry-cpp \
&& git submodule update --init --recursive
RUN cmake -S /opt/opentelemetry-cpp \
-B /opt/opentelemetry-cpp/build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=14 \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DWITH_OTLP_HTTP=ON \
-DWITH_OTLP_GRPC=OFF \
-DBUILD_TESTING=OFF \
-DWITH_EXAMPLES=OFF \
-DCMAKE_INSTALL_PREFIX=/usr/local \
&& cmake --build /opt/opentelemetry-cpp/build \
--parallel $(nproc) \
&& cmake --install /opt/opentelemetry-cpp/build \
&& rm -rf /opt/opentelemetry-cpp
RUN ldconfig /usr/local/lib
Then, in next step keep you existing WORKDIR command as unchanged.
Example:
WORKDIR /app
Add the clone motadata wrapper after your WORKDIR and before your COPY commands.
RUN git clone --depth 1 \
https://github.com/motadata2025/motadata-apm-cpp-instrumentation.git \
motadata-cpp
Then, your existing COPY and BUILD commands must be unchanged as below example.
COPY . .
RUN cmake -S . -B build && cmake --build build
ENTRYPOINT ["./build/YourApp"]
The SDK's runtime .so libraries must therefore be explicitly copied from the builder into the runner stage, otherwise the app can be crashed at startup with a missing shared library error.
Your dockerfile may have the below section, which should be unchanged:
FROM ubuntu:24.04 AS builder
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y cmake g++ make && \
rm -rf /var/lib/apt/lists/*
Add the below instrumentation snippets, under your existing apt-get block.
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
pkg-config \
libcurl4-openssl-dev \
libssl-dev \
libprotobuf-dev \
protobuf-compiler \
&& rm -rf /var/lib/apt/lists/*
RUN git clone --depth 1 --branch v1.23.0 \
https://github.com/open-telemetry/opentelemetry-cpp.git \
/opt/opentelemetry-cpp \
&& cd /opt/opentelemetry-cpp \
&& git submodule update --init --recursive
RUN cmake -S /opt/opentelemetry-cpp \
-B /opt/opentelemetry-cpp/build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=14 \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DWITH_OTLP_HTTP=ON \
-DWITH_OTLP_GRPC=OFF \
-DBUILD_TESTING=OFF \
-DWITH_EXAMPLES=OFF \
-DCMAKE_INSTALL_PREFIX=/usr/local \
&& cmake --build /opt/opentelemetry-cpp/build \
--parallel $(nproc) \
&& cmake --install /opt/opentelemetry-cpp/build \
&& rm -rf /opt/opentelemetry-cpp
RUN ldconfig /usr/local/lib
Then, in next step keep you existing WORKDIR command as unchanged.
Example:
WORKDIR /app
Add the clone motadata wrapper after your WORKDIR and before your COPY commands.
RUN git clone --depth 1 \
https://github.com/motadata2025/motadata-apm-cpp-instrumentation.git \
motadata-cpp
Then, your existing COPY and BUILD commands must be unchanged as below example.
COPY . .
RUN cmake -S . -B build && cmake --build build
Runner Satge
You may have the following snippet which should be untouched.
FROM ubuntu:24.04
Now, add the below snippets, at the TOP of your runner stage.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
libcurl4 \
libprotobuf32t64 \
libssl3 \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local/lib /usr/local/lib
RUN ldconfig /usr/local/lib
Keep your existing runner stage lines unchaged as displayed in below example.
RUN useradd -m -s /bin/bash appuser
USER appuser
WORKDIR /appdir
COPY --from=builder /appdir/build/YourApp .
EXPOSE 8080
ENTRYPOINT ["./YourApp"]
4. Add .dockerignore
cmake-build-debug/
build/
5. Update CMakeLists.txt
Update your CMakeLists.txt to include the Motadata wrapper.
cmake_minimum_required(VERSION 3.16)
project(CPPDockerApp1)
set(CMAKE_CXX_STANDARD 17)
find_package(Threads REQUIRED)
add_subdirectory(motadata-cpp)
add_executable(CPPDockerApp1 main.cpp)
The add_subdirectory(motadata-cpp) should always come before add_executable(). Also,
After this, you need to add motadata-cpp/include after the mentioned source directory mentioned under the target_include_directories.
target_include_directories(CPPDockerApp1 PRIVATE
${CMAKE_SOURCE_DIR}
motadata-cpp/include
)
Now, add motadata for target_link_libraries. Also, if curl, and pthread is not available add them as it is required by wrapper.
target_link_libraries(CPPDockerApp1 PRIVATE
Threads::Threads
motadata
curl
pthread
)
6. Include the Motadata Header
In every .cpp file where spans will be created, add:
#include "motadata.h"
Initialize Telemetry
Initialize telemetry once, at the top of main():
#include "motadata.h"
#include <iostream>
int main() {
motadata::TelemetryConfig cfg;
cfg.service_name = "your-service-name";
cfg.service_version = "1.0.0";
cfg.collector_url = "http://host.docker.internal:4318";
cfg.debug_print_to_console = true;
if (!motadata::initTelemetry(cfg)) {
std::cerr << "[telemetry] Warning: init failed, continuing without tracing\n";
}
runYourApplication();
motadata::shutdown();
return 0;
}
| Config Field | Explanation |
|---|---|
service_name | Defines how your service appears in the observability UI. Use a short, lowercase, descriptive name. Example: order-service, auth-api, data-processor. |
service_version | Specifies your application version string. This is useful for identifying which release introduced a problem. Example: 2.1.0, release-47. |
collector_url | Specifies the URL of the Motadata Instrumentation Collector. The default value is http://host.docker.internal:4318. Change this only if the Collector is running on a different host or port. |
debug_print_to_console | When set to true, every span is also printed to stdout in a human-readable format. This is useful during development and troubleshooting. Set it to false in production because it adds unnecessary log noise. |
7. Create Spans
Basic span example:
void processOrder(const std::string& order_id, double total) {
auto span = motadata::startSpan("processOrder");
span->setAttr("order.id", order_id);
span->setAttr("order.total", total);
span->setAttr("order.currency", "USD");
validateOrder(order_id);
chargePayment(order_id, total);
sendConfirmation(order_id);
span->setOk();
span->end();
}
Error handling example:
void chargePaymentGateway(const std::string& order_id, double amount) {
auto span = motadata::startSpan("chargePaymentGateway");
span->setAttr("order.id", order_id);
span->setAttr("amount", amount);
try {
callGatewayAPI(order_id, amount);
span->setOk();
span->end();
} catch (const std::exception& e) {
span->recordException(e);
span->end();
throw;
}
}
Nested spans
void processOrder() {
auto span = motadata::startSpan("processOrder");
fetchOrderFromDatabase();
chargePaymentGateway();
sendConfirmationEmail();
span->setOk();
span->end();
}
void fetchOrderFromDatabase() {
auto span = motadata::startSpan("fetchOrderFromDatabase");
span->setAttr("db.system", "postgresql");
span->setAttr("db.name", "orders");
span->setAttr("db.statement", "SELECT * FROM orders WHERE id = ?");
span->setAttr("db.rows_returned", 1);
span->setOk();
span->end();
}
Cross-thread example:
void processOrdersInBackground() {
auto parent = motadata::startSpan("processOrdersInBackground");
parent->setAttr("batch.size", 100);
auto ctx = parent->getContext();
std::thread worker([ctx]() {
auto child = motadata::startSpan("WorkerThread::ProcessBatch", ctx);
child->setAttr("thread.type", "batch-worker");
child->setOk();
child->end();
});
worker.join();
parent->setOk();
parent->end();
}
HTTP propagation example:
void callInventoryService(const std::string& sku) {
auto span = motadata::startSpan("callInventoryService");
span->setAttr("http.method", "GET");
span->setAttr("http.url", "http://inventory-service/api/stock/" + sku);
motadata::HttpHeaders headers;
headers["Content-Type"] = "application/json";
motadata::injectHeaders(headers);
span->setAttr("http.status_code", 200);
span->setOk();
span->end();
}
8. Build Docker Image
docker build .
Or with tag:
docker build -t cpp.docker.image .
Check the image using:
docker images
Expected Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
cpp.docker.image latest 0e3565ac930e 7 days ago 2.22GB
9. Run the Container
Using image name:
docker run -d \
--add-host=host.docker.internal:host-gateway \
cpp.docker.image
Using image ID:
docker run -d \
--add-host=host.docker.internal:host-gateway \
<image_id>
Step 9: Verify Container Execution
docker ps
docker logs -f <container_id>
If debug_print_to_console = true, spans appear in container logs during execution.
Important Rules
| Rule | Explanation |
|---|---|
Always call span->end() | Every span must be ended on all code paths. |
Always call motadata::shutdown() | Buffered spans are flushed before exit. |
Call initTelemetry() only once | Initialize once at startup before any tracing begins. |
| Never terminate the app if telemetry initialization fails | Tracing failure must not block application execution. |
| Never share a span across threads | Use span context for cross-thread parent-child relationships. |
Step4: Verify Trace Collection
Once the application is running, verify the following:
- Confirm that the service has been registered successfully.
- On the service registration screen, the Service Trace Collection Status should display Running.
- The traces should start appearing in the APM Explorer screen.