Each subdirectory contains a C/C++ application that uses the library named after the directory (CivetWeb, cpp-httplib + cpptrace, libcurl, gRPC, librdkafka, mongocxx, MySQL X DevAPI, hiredis) and traces it with pinpoint-cpp-agent.
Two build systems are supported:
- CMake — builds pinpoint-cpp-agent via
FetchContent. All examples build (macOS / Linux). - Bazel — uses pinpoint-cpp-agent's own bzlmod build directly. Requires Bazel 8. On macOS,
cpptrace_exampleis excluded (libunwind compatibility).
| Directory | Library | Binaries |
|---|---|---|
| civetweb/ | CivetWeb (HTTP server, C) | civetweb_example |
| cpptrace/ | cpptrace + cpp-httplib | cpptrace_example |
| curl/ | libcurl + cpp-httplib | curl_web_example |
| grpc/ | gRPC | grpc_client, grpc_server |
| kafka/ | librdkafka + cpp-httplib | kafka_web_producer, kafka_consumer |
| mongodb/ | mongo-cxx-driver | mongo_example |
| mysql/ | MySQL Connector/C++ X DevAPI + cpp-httplib | mysql_example |
| redis/ | hiredis | redis_example |
brew install cmake ninja bazelisk pkg-config
brew install hiredis librdkafka mongo-cxx-driver mysql-connector-c++
# civetweb, cpptrace, and cpp-httplib are fetched automatically at build time.On a Linux distro, install the equivalent packages with your package manager (libcurl4-openssl-dev, libhiredis-dev, librdkafka-dev, libmongocxx-dev, libmysqlcppconn-dev, etc.).
Each example sends trace data to the collector at 127.0.0.1:9991/9992/9993 by default, or to whatever the YAML file pointed to by PINPOINT_CPP_CONFIG_FILE specifies. The examples still run if no collector is reachable — the trace exports just fail silently.
Sample YAML (/tmp/pinpoint-config.yaml):
ApplicationName: my-app
AgentId: my-agent
Collector:
Ip: 127.0.0.1
GrpcPort: 9991
StatPort: 9992
SpanPort: 9993docker-compose.yml defines the four services:
docker compose up -d # start all four
docker compose up -d redis # start one
docker compose down -v # stop and wipe volumesEndpoints:
- kafka:
localhost:9092(topic:test-topic) - mongodb:
localhost:27017 - mysql:
localhost:3306(classic),localhost:33060(X Protocol). userroot/ passwordpinpoint123, dbtest - redis:
localhost:6379
cmake --preset debug # or --preset release
cmake --build build/debugBinaries land in build/debug/bin/. The first build takes ~5–10 minutes because pinpoint-cpp-agent fetches and compiles gRPC; subsequent incremental builds are fast.
Build a single example:
cmake --build build/debug --target redis_examplebazel build //... # everything
bazel build //redis:redis_example # one targetBinaries land at bazel-bin/<example>/<binary>. On macOS, cpptrace_example is excluded via target_compatible_with — use the CMake build instead.
A CivetWeb HTTP server traced with pinpoint-cpp-agent's C API (pt_*). Manually constructs the header carriers and calls pt_agent_new_span_with_reader / pt_trace_http_server_request / pt_trace_http_server_response.
Build & run:
# CMake
cmake --build build/debug --target civetweb_example
./build/debug/bin/civetweb_example [pinpoint-config.yaml]
# Bazel
bazel run //civetweb:civetweb_exampleEndpoints (localhost:8080):
GET /— landing HTMLGET /api/users— dummy users JSON; response headers are recorded on the spanGET /api/health— health check, also traced
Test:
curl http://localhost:8080/api/users
curl http://localhost:8080/api/healthPress Enter on the server console to stop the server.
A cpp-httplib server that attaches a cpptrace-captured call stack to a Pinpoint span via SetError. Outgoing HTTP requests carry the trace context injected into the request headers.
Build & run:
# CMake (Bazel disabled on macOS — libunwind incompatibility)
cmake --build build/debug --target cpptrace_example
./build/debug/bin/cpptrace_exampleConfiguration is provided via env vars (defaults to /tmp/pinpoint-config.yaml):
PINPOINT_CPP_CONFIG_FILE=/path/to/config.yaml \
PINPOINT_CPP_APPLICATION_NAME=my-cpptrace-demo \
./build/debug/bin/cpptrace_exampleEndpoints (localhost:8088):
GET /users/{id}?name=...— returns the pathidand thenamequery param as JSONGET /outgoing?host=...&path=...— issues a cpp-httplib client call to that URL and returns the response. On failure, attaches the cpptrace stack to the span viaSetError
Test:
curl 'http://localhost:8088/users/123?name=foo'
curl 'http://localhost:8088/outgoing?host=localhost:9000&path=/bar' # fails -> traced call stackIssues outbound HTTP requests with libcurl while injecting the Pinpoint trace context into the request headers via curl_slist_append.
Build & run:
# CMake
cmake --build build/debug --target curl_web_example
./build/debug/bin/curl_web_example
# Bazel
bazel run //curl:curl_web_exampleThe default target URL is http://google.com. Override with an env var:
TARGET_URL=https://httpbin.org/get ./build/debug/bin/curl_web_exampleEndpoint (localhost:8091):
GET /run_request[?url=...]— calls the URL from theurlquery param (orTARGET_URL) via cURL
Test:
curl 'http://localhost:8091/run_request?url=https://httpbin.org/get'Custom ClientInterceptor / ServerInterceptor inject and extract the Pinpoint trace context through gRPC metadata. All four RPC patterns (Unary, Server-Streaming, Client-Streaming, Bidi) are traced.
Build & run:
# CMake
cmake --build build/debug --target grpc_server grpc_client
# Terminal 1
./build/debug/bin/grpc_server # listens on 0.0.0.0:50051
# Terminal 2
./build/debug/bin/grpc_client
# Bazel (same pattern)
bazel run //grpc:grpc_server
bazel run //grpc:grpc_clientProto: testapp.proto. Service grpcdemo.Hello with four methods.
grpc_client runs unary → server-streaming → bidi calls in sequence on startup, then exits.
The producer publishes a message with the trace context injected into Kafka message headers; the consumer extracts it and starts a new span as a child of the producer's trace.
Build & run:
docker compose up -d kafka
# CMake
cmake --build build/debug --target kafka_web_producer kafka_consumer
# Terminal 1: start the consumer first (subscribes to test-topic)
./build/debug/bin/kafka_consumer
# Terminal 2: producer (HTTP server on port 8090)
./build/debug/bin/kafka_web_producer
# Bazel
bazel run //kafka:kafka_consumer
bazel run //kafka:kafka_web_producerThe broker address can be overridden via KAFKA_BROKERS (default localhost:9092).
Producer endpoint (localhost:8090):
GET /run_producer[?message=...]— produces the message totest-topic
Test:
curl 'http://localhost:8090/run_producer?message=hello-pinpoint'
# Watch for "Consumed message: hello-pinpoint" in the kafka_consumer terminalEach MongoDB operation is wrapped in a SpanEvent that records the collection name and a query description as annotations.
Build & run:
docker compose up -d mongodb
# CMake
cmake --build build/debug --target mongo_example
./build/debug/bin/mongo_example
# Bazel
bazel run //mongodb:mongo_exampleOverride the URI via MONGO_URI (default mongodb://localhost:27017).
This example runs in batch mode (it is not a server): in db testdb / collection testcollection it performs Insert → Find → Update → Delete, then exits.
Uses X Protocol (mysqlx://, port 33060) for SQL execution; each query is wrapped in a span event. Hitting /db-demo runs a SELECT/INSERT/UPDATE/DELETE/transaction sequence.
Build & run:
docker compose up -d mysql
# CMake
cmake --build build/debug --target mysql_example
./build/debug/bin/mysql_example
# Bazel
bazel run //mysql:mysql_exampleConnection settings can be overridden via env vars (MYSQL_HOST, MYSQL_PORT, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD).
Endpoints (localhost:8089):
GET /db-demo— runs the demo scenario, returns JSONGET /status— service metadata
Test:
curl http://localhost:8089/status
curl http://localhost:8089/db-demoThe initial schema and seed data come from mysql/init.sql, applied on the container's first startup (demo_users table).
Each Redis command is wrapped in a SpanEvent with SERVICE_TYPE_REDIS.
Build & run:
docker compose up -d redis
# CMake
cmake --build build/debug --target redis_example
./build/debug/bin/redis_example
# Bazel
bazel run //redis:redis_exampleHost / port overrides: REDIS_HOST, REDIS_PORT.
This example is also batch-mode: PING → SET → GET → INCR → LPUSH (loop) → LRANGE, then exits.
- The first CMake build is very slow — pinpoint-cpp-agent uses
FetchContentto pull and compile gRPC + protobuf + abseil + BoringSSL. It's cached after the first run. bazel: command not found—brew install bazelisk. The wrapper reads.bazelversionand downloads Bazel 8 automatically.cpptrace_examplewon't build under Bazel on macOS — cpptrace BCR 1.0.4 forces libunwind, which doesn't compile on macOS. Use the CMake build for this example.- MongoDB / MySQL / Kafka connection refused — verify the service is running (
docker compose psshowsUp (healthy)). - Pinpoint traces don't show up in the collector — confirm the collector is running, and that the IP/port in
PINPOINT_CPP_CONFIG_FILE(orpinpoint::SetConfigString) match.