Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 77 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
cmake_minimum_required(VERSION 3.13)
# Note: Make sure that this version is the same as that in
# "./CheckRequiredCMakeVersion.cmake".
cmake_minimum_required(VERSION 3.24)

project(dd-trace-cpp)

option(BUILD_COVERAGE "Build code with code coverage profiling instrumentation" OFF)
option(BUILD_EXAMPLE "Build the example program (example/)" OFF)

set(CMAKE_BUILD_TYPE "RelWithDebInfo")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

include(ProcessorCount)
ProcessorCount(NUM_PROCESSORS)
set(MAKE_JOB_COUNT ${NUM_PROCESSORS} CACHE STRING "Number of jobs to use when building libcurl")

include (ExternalProject)
ExternalProject_Add(curl
URL "https://github.com/curl/curl/releases/download/curl-7_85_0/curl-7.85.0.tar.gz"
URL_MD5 "4e9eb4f434e9be889e510f038754d3de"
BUILD_IN_SOURCE 1
DOWNLOAD_EXTRACT_TIMESTAMP 0
SOURCE_DIR ${CMAKE_BINARY_DIR}/curl
CONFIGURE_COMMAND ${CMAKE_BINARY_DIR}/curl/configure --prefix=${CMAKE_BINARY_DIR} --disable-ftp --disable-ldap --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-smtp --disable-gopher --without-ssl --disable-crypto-auth --without-axtls --without-zlib --disable-rtsp --enable-shared=no --enable-static=yes --with-pic --without-brotli
BUILD_COMMAND make -j16
BUILD_COMMAND make -j${MAKE_JOB_COUNT}
INSTALL_COMMAND make install
)

Expand All @@ -40,7 +49,8 @@ if(BUILD_COVERAGE)
set(COVERAGE_LIBRARIES gcov)
endif()

add_library(dd_trace_cpp
add_library(dd_trace_cpp SHARED)
target_sources(dd_trace_cpp PRIVATE
src/datadog/cerr_logger.cpp
src/datadog/clock.cpp
src/datadog/collector.cpp
Expand Down Expand Up @@ -89,17 +99,74 @@ add_library(dd_trace_cpp
src/datadog/version.cpp
)

add_dependencies(dd_trace_cpp curl)
# This library's public headers are just its source headers.
target_sources(dd_trace_cpp PUBLIC
FILE_SET public_headers
TYPE HEADERS
BASE_DIRS src/
FILES
src/datadog/cerr_logger.h
src/datadog/clock.h
src/datadog/collector.h
src/datadog/collector_response.h
# src/datadog/curl.h except for curl.h
src/datadog/datadog_agent_config.h
src/datadog/datadog_agent.h
src/datadog/default_http_client.h
src/datadog/dict_reader.h
src/datadog/dict_writer.h
src/datadog/environment.h
src/datadog/error.h
src/datadog/event_scheduler.h
src/datadog/expected.h
src/datadog/glob.h
src/datadog/http_client.h
src/datadog/id_generator.h
src/datadog/json_fwd.hpp
src/datadog/json.hpp
src/datadog/limiter.h
src/datadog/logger.h
src/datadog/msgpack.h
src/datadog/net_util.h
src/datadog/null_collector.h
src/datadog/parse_util.h
src/datadog/propagation_styles.h
src/datadog/rate.h
src/datadog/sampling_decision.h
src/datadog/sampling_mechanism.h
src/datadog/sampling_priority.h
src/datadog/sampling_util.h
src/datadog/span_config.h
src/datadog/span_data.h
src/datadog/span_defaults.h
src/datadog/span.h
src/datadog/span_matcher.h
src/datadog/span_sampler_config.h
src/datadog/span_sampler.h
src/datadog/tag_propagation.h
src/datadog/tags.h
src/datadog/threaded_event_scheduler.h
src/datadog/tracer_config.h
src/datadog/tracer.h
src/datadog/trace_sampler_config.h
src/datadog/trace_sampler.h
src/datadog/trace_segment.h
src/datadog/version.h
)

# Make the build libcurl visible to dd_trace_cpp and its dependents.
target_include_directories(dd_trace_cpp PUBLIC ${CMAKE_BINARY_DIR}/include)
add_dependencies(dd_trace_cpp curl)

# This library's public headers are just its source headers.
target_include_directories(dd_trace_cpp INTERFACE src/)
# Make the build libcurl visible to dd_trace_cpp, but not to its dependents.
target_include_directories(dd_trace_cpp PRIVATE ${CMAKE_BINARY_DIR}/include)

# Any dependent target that's linking this library will also need curl and threads.
# Linking this library requires libcurl and threads.
find_package(Threads REQUIRED)
target_link_libraries(dd_trace_cpp INTERFACE ${CMAKE_BINARY_DIR}/lib/libcurl.a Threads::Threads)
target_link_libraries(dd_trace_cpp PRIVATE ${CMAKE_BINARY_DIR}/lib/libcurl.a PUBLIC Threads::Threads)

# When installing, install the library and its public headers.

install(TARGETS dd_trace_cpp
FILE_SET public_headers)

if(BUILD_TESTING)
add_subdirectory(test)
Expand Down
11 changes: 11 additions & 0 deletions CheckRequiredCMakeVersion.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# "bin/install-cmake" loads this file with "cmake -P [...]" to check whether the
# installed version of cmake is recent enough.
#
# If "cmake -P [...]" exits with status code zero, then the versions are
# compatible.
#
# If it exits with another status code, then either the versions are
# incompatible or something else went wrong.
#
# Note: Make sure that this version is the same as that in "./CMakeLists.txt".
cmake_minimum_required(VERSION 3.24)
99 changes: 47 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,47 @@
Check out the latest [testing code coverage report][1].

Logical Component Relationships
-------------------------------
- Vertices are components.
- Edges are ownership relationships between components. Each edge is labeled
by the kind of "smart pointer" that could implement that kind of
relationship.
- Components containing a padlock are protected by a mutex.

![diagram](ownership.svg)

Code Component Relationships
----------------------------
![another diagram](includes.svg)

Example Usage
-------------
TODO

Objects
-------
- _Span_ has a beginning, end, and tags. It is associated with a _TraceSegment_.
- _TraceSegment_ is part of a trace. It makes sampling decisions, detects when
it is finished, and sends itself to the _Collector_.
- _Collector_ receives trace segments. It provides a callback to deliver
sampler modifications, if applicable.
- _Tracer_ is responsible for creating trace segments. It contains the
instances of, and configuration for, the _Collector_, _TraceSampler_, and
_SpanSampler_. A tracer is created from a _TracerConfig_.
- _TraceSampler_ is used by trace segments to decide when to keep or drop
themselves.
- _SpanSampler_ is used by trace segments to decide which spans to keep when
the segment is dropped.
- _TracerConfig_ contains all of the information needed to configure the collector,
trace sampler, and span sampler, as well as defaults for span properties.

Intended usage is:

1. Create a `TracerConfig`.
2. Use the `TracerConfig` to create a `Tracer`.
3. Use the `Tracer` to create and/or extract local root `Span`s.
4. Use `Span` to create children and/or inject context.
5. Use a `Span`'s `TraceSegment` to perform trace-wide operations.
6. When all `Span`s in ` TraceSegment` are finished, the segment is sent to the
`Collector`.

Different instances of `Tracer` are independent of each other. If an
application wishes to reconfigure tracing at runtime, it can create another
`Tracer` using the new configuration.

[1]: https://datadog.github.io/dd-trace-cpp/datadog
Build
-----
### `cmake && make && make install` Style Build
Build this library from source using [CMake][1]. Installation places a shared
library and public headers into the appropriate system directories
(`/usr/local/[...]`), or to a specified installation prefix.

A recent version of CMake is required (3.24), which might not be in your
system's package manager. [bin/install-cmake](bin/install-cmake) is an installer
for a recent CMake.

Here is how to install dd-trace-cpp into `.install/` within the source
repository.
```shell
$ git clone 'https://github.com/datadog/dd-trace-cpp'
$ cd dd-trace-cpp
$ bin/install-cmake
$ mkdir .install
$ mkdir .build
$ cd .build
$ cmake -DCMAKE_INSTALL_PREFIX=../.install ..
$ make -j $(nproc)
$ make install
$ find ../.install -type d
```

To instead install into `/usr/local/`, omit the `.install` directory and the
`-DCMAKE_INSTALL_PREFIX=../.install` option.

Then, when building an executable that uses `dd-trace-cpp`, specify the path to
the installed headers using an appropriate `-I` option. If the library was
installed into the default system directories, then the `-I` option is not
needed.
```shell
$ c++ -I/path/to/dd-trace-cpp/.install/include -c -o my_app.o my_app.cpp
```

When linking an executable that uses `dd-trace-cpp`, specify linkage to the
built library using the `-ldd_trace_cpp` option and an appropriate `-L` option.
If the library was installed into the default system directories, then the `-L`
options is not needed. The `-ldd_trace_cpp` option is always needed.
```shell
$ c++ -o my_app my_app.o -L/path/to/dd-trace-cpp/.install/lib -ldd_trace_cpp
```
<!-- TODO: Do those commands need -pthread as well? -->

[1]: https://cmake.org/
5 changes: 4 additions & 1 deletion bin/example
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ if [ "$build_only" -eq 1 ]; then
exit
fi

trap 'docker compose --project-directory ../example down' INT

echo 'Running example...'
if [ "$DD_API_KEY" = '' ]; then
>&2 echo "The DD_API_KEY environment variable must be set to a Datadog API key."
exit 1
fi
docker compose --project-directory ../example up --detach --remove-orphans
sleep 3
# docker compose --project-directory ../example logs --follow &
./example/example"$@"
docker compose --project-directory ../example down
# wait
46 changes: 46 additions & 0 deletions bin/install-cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/sh

# Install a recent binary release of cmake.
# Kitware produces a self-installing tarball.

if [ "$(uname)" != Linux ]; then
>&2 echo "This installer requires Linux, but instead you're running $(uname)."
exit 1
fi

VERSION=3.24.2
REPO=$(dirname "$0")/..

# If a suitably recent version of cmake is already installed, then don't bother.
if >/dev/null command -v cmake && >/dev/null 2>&1 cmake -P "$REPO/CheckRequiredCMakeVersion.cmake"; then
echo 'A suitable version of cmake is already installed.'
exit
fi

for required in wget sed; do
if ! >/dev/null command -v "$required"; then
>&2 echo "This installer requires $required."
exit 2
fi
done

ARCHITECTURE=$(uname -m)
INSTALLER=cmake-${VERSION}-linux-${ARCHITECTURE}.sh
URL=https://github.com/Kitware/CMake/releases/download/v${VERSION}/${INSTALLER}

maybe_sudo() {
if [ "$(id -u)" -eq 0 ]; then
"$@"
else
sudo "$@"
fi
}

cd /tmp
if ! wget "${URL}"; then
>&2 echo "wget failed to download \"${URL}\"."
exit 3
fi
chmod +x "${INSTALLER}"
maybe_sudo ./"${INSTALLER}" --skip-license --prefix=/usr/local --exclude-subdir
rm "${INSTALLER}"
4 changes: 2 additions & 2 deletions Makefile → doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ all: ownership.svg includes.svg
%.svg: %.dot
dot -Grankdir=LR -Tsvg -o $@ $<

includes.dot: $(wildcard src/*)
raco graph-includes --exclude-std-c --exclude-std-cpp --exclude-posix --extension h --extension cpp src/ >$@
includes.dot: $(wildcard ../src/*)
raco graph-includes --exclude-std-c --exclude-std-cpp --exclude-posix --extension h --extension cpp ../src/ >$@
52 changes: 52 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Check out the latest [testing code coverage report][1].

Logical Component Relationships
-------------------------------
- Vertices are components.
- Edges are ownership relationships between components. Each edge is labeled
by the kind of "smart pointer" that could implement that kind of
relationship.
- Components containing a padlock are protected by a mutex.

![diagram](ownership.svg)

Code Component Relationships
----------------------------
![another diagram](includes.svg)

Example Usage
-------------
TODO

Objects
-------
- _Span_ has a beginning, end, and tags. It is associated with a _TraceSegment_.
- _TraceSegment_ is part of a trace. It makes sampling decisions, detects when
it is finished, and sends itself to the _Collector_.
- _Collector_ receives trace segments. It provides a callback to deliver
sampler modifications, if applicable.
- _Tracer_ is responsible for creating trace segments. It contains the
instances of, and configuration for, the _Collector_, _TraceSampler_, and
_SpanSampler_. A tracer is created from a _TracerConfig_.
- _TraceSampler_ is used by trace segments to decide when to keep or drop
themselves.
- _SpanSampler_ is used by trace segments to decide which spans to keep when
the segment is dropped.
- _TracerConfig_ contains all of the information needed to configure the collector,
trace sampler, and span sampler, as well as defaults for span properties.

Intended usage is:

1. Create a `TracerConfig`.
2. Use the `TracerConfig` to create a `Tracer`.
3. Use the `Tracer` to create and/or extract local root `Span`s.
4. Use `Span` to create children and/or inject context.
5. Use a `Span`'s `TraceSegment` to perform trace-wide operations.
6. When all `Span`s in ` TraceSegment` are finished, the segment is sent to the
`Collector`.

Different instances of `Tracer` are independent of each other. If an
application wishes to reconfigure tracing at runtime, it can create another
`Tracer` using the new configuration.

[1]: https://datadog.github.io/dd-trace-cpp/datadog
File renamed without changes.
Loading