diff --git a/CMakeLists.txt b/CMakeLists.txt index aa8bc32a..8f690230 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) @@ -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 @@ -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) diff --git a/CheckRequiredCMakeVersion.cmake b/CheckRequiredCMakeVersion.cmake new file mode 100644 index 00000000..bb412638 --- /dev/null +++ b/CheckRequiredCMakeVersion.cmake @@ -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) diff --git a/README.md b/README.md index 6fff21e5..a520f373 100644 --- a/README.md +++ b/README.md @@ -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 +``` + + +[1]: https://cmake.org/ diff --git a/bin/example b/bin/example index 329cdfa3..5139ca41 100755 --- a/bin/example +++ b/bin/example @@ -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 diff --git a/bin/install-cmake b/bin/install-cmake new file mode 100755 index 00000000..66761dcd --- /dev/null +++ b/bin/install-cmake @@ -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}" diff --git a/Makefile b/doc/Makefile similarity index 65% rename from Makefile rename to doc/Makefile index 3d3c3507..7631f39a 100644 --- a/Makefile +++ b/doc/Makefile @@ -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/ >$@ diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000..6fff21e5 --- /dev/null +++ b/doc/README.md @@ -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 diff --git a/decisions.md b/doc/decisions.md similarity index 100% rename from decisions.md rename to doc/decisions.md diff --git a/doc/includes.dot b/doc/includes.dot new file mode 100644 index 00000000..5e6e4799 --- /dev/null +++ b/doc/includes.dot @@ -0,0 +1,296 @@ +digraph G { + node0 [label="span_data.cpp"]; + node1 [label="threaded_event_scheduler.cpp"]; + node2 [label="rate.cpp"]; + node3 [label="default_http_client_null.cpp"]; + node4 [label="trace_segment.h"]; + node5 [label="dict_writer.h"]; + node6 [label="tag_propagation.cpp"]; + node7 [label="json.hpp"]; + node8 [label="span_sampler.h"]; + node9 [label="dict_reader.cpp"]; + node10 [label="tags.h"]; + node11 [label="tracer_config.h"]; + node12 [label="curl/curl.h"]; + node13 [label="expected.h"]; + node14 [label="limiter.h"]; + node15 [label="span.h"]; + node16 [label="sampling_mechanism.cpp"]; + node17 [label="logger.cpp"]; + node18 [label="rate.h"]; + node19 [label="sampling_util.h"]; + node20 [label="sampling_decision.h"]; + node21 [label="span_data.h"]; + node22 [label="datadog_agent_config.h"]; + node23 [label="sampling_mechanism.h"]; + node24 [label="msgpack.cpp"]; + node25 [label="default_http_client.h"]; + node26 [label="sampling_util.cpp"]; + node27 [label="datadog_agent_config.cpp"]; + node28 [label="span.cpp"]; + node29 [label="json_fwd.hpp"]; + node30 [label="event_scheduler.cpp"]; + node31 [label="datadog_agent.h"]; + node32 [label="error.h"]; + node33 [label="event_scheduler.h"]; + node34 [label="tag_propagation.h"]; + node35 [label="clock.h"]; + node36 [label="logger.h"]; + node37 [label="curl.h"]; + node38 [label="span_defaults.h"]; + node39 [label="span_defaults.cpp"]; + node40 [label="tracer.h"]; + node41 [label="threaded_event_scheduler.h"]; + node42 [label="parse_util.h"]; + node43 [label="expected.cpp"]; + node44 [label="collector.cpp"]; + node45 [label="id_generator.cpp"]; + node46 [label="sampling_decision.cpp"]; + node47 [label="trace_sampler.cpp"]; + node48 [label="sampling_priority.cpp"]; + node49 [label="span_sampler.cpp"]; + node50 [label="collector.h"]; + node51 [label="curl.cpp"]; + node52 [label="null_collector.cpp"]; + node53 [label="cerr_logger.cpp"]; + node54 [label="collector_response.h"]; + node55 [label="msgpack.h"]; + node56 [label="trace_sampler.h"]; + node57 [label="span_config.cpp"]; + node58 [label="dict_writer.cpp"]; + node59 [label="trace_sampler_config.cpp"]; + node60 [label="span_config.h"]; + node61 [label="environment.h"]; + node62 [label="datadog_agent.cpp"]; + node63 [label="winsock.h"]; + node64 [label="environment.cpp"]; + node65 [label="id_generator.h"]; + node66 [label="tracer_config.cpp"]; + node67 [label="net_util.cpp"]; + node68 [label="parse_util.cpp"]; + node69 [label="http_client.cpp"]; + node70 [label="null_collector.h"]; + node71 [label="charconv"]; + node72 [label="version.h"]; + node73 [label="span_sampler_config.h"]; + node74 [label="span_matcher.h"]; + node75 [label="version.cpp"]; + node76 [label="propagation_styles.cpp"]; + node77 [label="dict_reader.h"]; + node78 [label="span_matcher.cpp"]; + node79 [label="tracer.cpp"]; + node80 [label="default_http_client_curl.cpp"]; + node81 [label="http_client.h"]; + node82 [label="clock.cpp"]; + node83 [label="sampling_priority.h"]; + node84 [label="collector_response.cpp"]; + node85 [label="propagation_styles.h"]; + node86 [label="limiter.cpp"]; + node87 [label="net_util.h"]; + node88 [label="error.cpp"]; + node89 [label="trace_sampler_config.h"]; + node90 [label="cerr_logger.h"]; + node91 [label="tags.cpp"]; + node92 [label="trace_segment.cpp"]; + node93 [label="span_sampler_config.cpp"]; + subgraph U { + edge [dir=none]; + } + subgraph D { + node0 -> node38 []; + node0 -> node60 []; + node0 -> node21 []; + node0 -> node55 []; + node0 -> node10 []; + node0 -> node32 []; + node1 -> node41 []; + node2 -> node18 []; + node3 -> node25 []; + node4 -> node85 []; + node4 -> node20 []; + node4 -> node13 []; + node6 -> node34 []; + node6 -> node42 []; + node6 -> node32 []; + node8 -> node35 []; + node8 -> node73 []; + node8 -> node20 []; + node8 -> node14 []; + node9 -> node77 []; + node11 -> node73 []; + node11 -> node22 []; + node11 -> node89 []; + node11 -> node13 []; + node11 -> node32 []; + node11 -> node85 []; + node11 -> node38 []; + node13 -> node32 []; + node14 -> node35 []; + node14 -> node18 []; + node15 -> node35 []; + node15 -> node65 []; + node15 -> node32 []; + node16 -> node23 []; + node17 -> node36 []; + node17 -> node32 []; + node18 -> node13 []; + node19 -> node18 []; + node20 -> node23 []; + node20 -> node18 []; + node21 -> node35 []; + node21 -> node13 []; + node22 -> node13 []; + node22 -> node81 []; + node24 -> node55 []; + node24 -> node32 []; + node26 -> node19 []; + node27 -> node42 []; + node27 -> node22 []; + node27 -> node25 []; + node27 -> node61 []; + node27 -> node41 []; + node28 -> node4 []; + node28 -> node60 []; + node28 -> node5 []; + node28 -> node21 []; + node28 -> node15 []; + node28 -> node10 []; + node30 -> node33 []; + node31 -> node35 []; + node31 -> node50 []; + node31 -> node81 []; + node31 -> node33 []; + node33 -> node32 []; + node34 -> node13 []; + node37 -> node81 []; + node39 -> node38 []; + node40 -> node35 []; + node40 -> node65 []; + node40 -> node15 []; + node40 -> node32 []; + node40 -> node13 []; + node40 -> node11 []; + node41 -> node33 []; + node42 -> node13 []; + node43 -> node13 []; + node44 -> node50 []; + node45 -> node65 []; + node46 -> node20 []; + node47 -> node19 []; + node47 -> node56 []; + node47 -> node83 []; + node47 -> node54 []; + node47 -> node20 []; + node47 -> node21 []; + node48 -> node83 []; + node49 -> node23 []; + node49 -> node19 []; + node49 -> node83 []; + node49 -> node8 []; + node49 -> node21 []; + node50 -> node13 []; + node51 -> node36 []; + node51 -> node37 []; + node51 -> node5 []; + node51 -> node42 []; + node51 -> node12 []; + node51 -> node81 []; + node51 -> node77 []; + node52 -> node70 []; + node53 -> node90 []; + node54 -> node18 []; + node55 -> node13 []; + node56 -> node35 []; + node56 -> node89 []; + node56 -> node18 []; + node56 -> node14 []; + node57 -> node60 []; + node58 -> node5 []; + node59 -> node42 []; + node59 -> node89 []; + node59 -> node7 []; + node59 -> node61 []; + node60 -> node35 []; + node62 -> node36 []; + node62 -> node22 []; + node62 -> node54 []; + node62 -> node7 []; + node62 -> node72 []; + node62 -> node31 []; + node62 -> node56 []; + node62 -> node5 []; + node62 -> node21 []; + node62 -> node55 []; + node64 -> node61 []; + node66 -> node42 []; + node66 -> node90 []; + node66 -> node11 []; + node66 -> node61 []; + node66 -> node70 []; + node66 -> node31 []; + node67 -> node87 []; + node67 -> node63 []; + node68 -> node71 []; + node68 -> node42 []; + node68 -> node32 []; + node69 -> node81 []; + node70 -> node50 []; + node73 -> node74 []; + node73 -> node13 []; + node73 -> node18 []; + node74 -> node13 []; + node74 -> node29 []; + node75 -> node72 []; + node76 -> node85 []; + node78 -> node7 []; + node78 -> node21 []; + node78 -> node74 []; + node78 -> node32 []; + node79 -> node4 []; + node79 -> node60 []; + node79 -> node40 []; + node79 -> node87 []; + node79 -> node8 []; + node79 -> node15 []; + node79 -> node31 []; + node79 -> node10 []; + node79 -> node34 []; + node79 -> node36 []; + node79 -> node56 []; + node79 -> node42 []; + node79 -> node21 []; + node79 -> node77 []; + node80 -> node25 []; + node80 -> node37 []; + node81 -> node13 []; + node81 -> node32 []; + node82 -> node35 []; + node83 -> node23 []; + node84 -> node54 []; + node86 -> node14 []; + node88 -> node32 []; + node89 -> node74 []; + node89 -> node13 []; + node89 -> node18 []; + node90 -> node36 []; + node91 -> node42 []; + node91 -> node10 []; + node92 -> node50 []; + node92 -> node54 []; + node92 -> node8 []; + node92 -> node21 []; + node92 -> node34 []; + node92 -> node36 []; + node92 -> node4 []; + node92 -> node71 []; + node92 -> node56 []; + node92 -> node5 []; + node92 -> node10 []; + node92 -> node32 []; + node93 -> node36 []; + node93 -> node73 []; + node93 -> node7 []; + node93 -> node13 []; + node93 -> node61 []; + } +} diff --git a/doc/includes.svg b/doc/includes.svg new file mode 100644 index 00000000..38f07ec7 --- /dev/null +++ b/doc/includes.svg @@ -0,0 +1,1747 @@ + + + + + + +G + + + +node0 + +span_data.cpp + + + +node10 + +tags.h + + + +node0->node10 + + + + + +node21 + +span_data.h + + + +node0->node21 + + + + + +node32 + +error.h + + + +node0->node32 + + + + + +node38 + +span_defaults.h + + + +node0->node38 + + + + + +node55 + +msgpack.h + + + +node0->node55 + + + + + +node60 + +span_config.h + + + +node0->node60 + + + + + +node1 + +threaded_event_scheduler.cpp + + + +node41 + +threaded_event_scheduler.h + + + +node1->node41 + + + + + +node2 + +rate.cpp + + + +node18 + +rate.h + + + +node2->node18 + + + + + +node3 + +default_http_client_null.cpp + + + +node25 + +default_http_client.h + + + +node3->node25 + + + + + +node4 + +trace_segment.h + + + +node13 + +expected.h + + + +node4->node13 + + + + + +node20 + +sampling_decision.h + + + +node4->node20 + + + + + +node85 + +propagation_styles.h + + + +node4->node85 + + + + + +node5 + +dict_writer.h + + + +node6 + +tag_propagation.cpp + + + +node6->node32 + + + + + +node34 + +tag_propagation.h + + + +node6->node34 + + + + + +node42 + +parse_util.h + + + +node6->node42 + + + + + +node7 + +json.hpp + + + +node8 + +span_sampler.h + + + +node14 + +limiter.h + + + +node8->node14 + + + + + +node8->node20 + + + + + +node35 + +clock.h + + + +node8->node35 + + + + + +node73 + +span_sampler_config.h + + + +node8->node73 + + + + + +node9 + +dict_reader.cpp + + + +node77 + +dict_reader.h + + + +node9->node77 + + + + + +node11 + +tracer_config.h + + + +node11->node13 + + + + + +node22 + +datadog_agent_config.h + + + +node11->node22 + + + + + +node11->node32 + + + + + +node11->node38 + + + + + +node11->node73 + + + + + +node11->node85 + + + + + +node89 + +trace_sampler_config.h + + + +node11->node89 + + + + + +node12 + +curl/curl.h + + + +node13->node32 + + + + + +node14->node18 + + + + + +node14->node35 + + + + + +node15 + +span.h + + + +node15->node32 + + + + + +node15->node35 + + + + + +node65 + +id_generator.h + + + +node15->node65 + + + + + +node16 + +sampling_mechanism.cpp + + + +node23 + +sampling_mechanism.h + + + +node16->node23 + + + + + +node17 + +logger.cpp + + + +node17->node32 + + + + + +node36 + +logger.h + + + +node17->node36 + + + + + +node18->node13 + + + + + +node19 + +sampling_util.h + + + +node19->node18 + + + + + +node20->node18 + + + + + +node20->node23 + + + + + +node21->node13 + + + + + +node21->node35 + + + + + +node22->node13 + + + + + +node81 + +http_client.h + + + +node22->node81 + + + + + +node24 + +msgpack.cpp + + + +node24->node32 + + + + + +node24->node55 + + + + + +node26 + +sampling_util.cpp + + + +node26->node19 + + + + + +node27 + +datadog_agent_config.cpp + + + +node27->node22 + + + + + +node27->node25 + + + + + +node27->node41 + + + + + +node27->node42 + + + + + +node61 + +environment.h + + + +node27->node61 + + + + + +node28 + +span.cpp + + + +node28->node4 + + + + + +node28->node5 + + + + + +node28->node10 + + + + + +node28->node15 + + + + + +node28->node21 + + + + + +node28->node60 + + + + + +node29 + +json_fwd.hpp + + + +node30 + +event_scheduler.cpp + + + +node33 + +event_scheduler.h + + + +node30->node33 + + + + + +node31 + +datadog_agent.h + + + +node31->node33 + + + + + +node31->node35 + + + + + +node50 + +collector.h + + + +node31->node50 + + + + + +node31->node81 + + + + + +node33->node32 + + + + + +node34->node13 + + + + + +node37 + +curl.h + + + +node37->node81 + + + + + +node39 + +span_defaults.cpp + + + +node39->node38 + + + + + +node40 + +tracer.h + + + +node40->node11 + + + + + +node40->node13 + + + + + +node40->node15 + + + + + +node40->node32 + + + + + +node40->node35 + + + + + +node40->node65 + + + + + +node41->node33 + + + + + +node42->node13 + + + + + +node43 + +expected.cpp + + + +node43->node13 + + + + + +node44 + +collector.cpp + + + +node44->node50 + + + + + +node45 + +id_generator.cpp + + + +node45->node65 + + + + + +node46 + +sampling_decision.cpp + + + +node46->node20 + + + + + +node47 + +trace_sampler.cpp + + + +node47->node19 + + + + + +node47->node20 + + + + + +node47->node21 + + + + + +node54 + +collector_response.h + + + +node47->node54 + + + + + +node56 + +trace_sampler.h + + + +node47->node56 + + + + + +node83 + +sampling_priority.h + + + +node47->node83 + + + + + +node48 + +sampling_priority.cpp + + + +node48->node83 + + + + + +node49 + +span_sampler.cpp + + + +node49->node8 + + + + + +node49->node19 + + + + + +node49->node21 + + + + + +node49->node23 + + + + + +node49->node83 + + + + + +node50->node13 + + + + + +node51 + +curl.cpp + + + +node51->node5 + + + + + +node51->node12 + + + + + +node51->node36 + + + + + +node51->node37 + + + + + +node51->node42 + + + + + +node51->node77 + + + + + +node51->node81 + + + + + +node52 + +null_collector.cpp + + + +node70 + +null_collector.h + + + +node52->node70 + + + + + +node53 + +cerr_logger.cpp + + + +node90 + +cerr_logger.h + + + +node53->node90 + + + + + +node54->node18 + + + + + +node55->node13 + + + + + +node56->node14 + + + + + +node56->node18 + + + + + +node56->node35 + + + + + +node56->node89 + + + + + +node57 + +span_config.cpp + + + +node57->node60 + + + + + +node58 + +dict_writer.cpp + + + +node58->node5 + + + + + +node59 + +trace_sampler_config.cpp + + + +node59->node7 + + + + + +node59->node42 + + + + + +node59->node61 + + + + + +node59->node89 + + + + + +node60->node35 + + + + + +node62 + +datadog_agent.cpp + + + +node62->node5 + + + + + +node62->node7 + + + + + +node62->node21 + + + + + +node62->node22 + + + + + +node62->node31 + + + + + +node62->node36 + + + + + +node62->node54 + + + + + +node62->node55 + + + + + +node62->node56 + + + + + +node72 + +version.h + + + +node62->node72 + + + + + +node63 + +winsock.h + + + +node64 + +environment.cpp + + + +node64->node61 + + + + + +node66 + +tracer_config.cpp + + + +node66->node11 + + + + + +node66->node31 + + + + + +node66->node42 + + + + + +node66->node61 + + + + + +node66->node70 + + + + + +node66->node90 + + + + + +node67 + +net_util.cpp + + + +node67->node63 + + + + + +node87 + +net_util.h + + + +node67->node87 + + + + + +node68 + +parse_util.cpp + + + +node68->node32 + + + + + +node68->node42 + + + + + +node71 + +charconv + + + +node68->node71 + + + + + +node69 + +http_client.cpp + + + +node69->node81 + + + + + +node70->node50 + + + + + +node73->node13 + + + + + +node73->node18 + + + + + +node74 + +span_matcher.h + + + +node73->node74 + + + + + +node74->node13 + + + + + +node74->node29 + + + + + +node75 + +version.cpp + + + +node75->node72 + + + + + +node76 + +propagation_styles.cpp + + + +node76->node85 + + + + + +node78 + +span_matcher.cpp + + + +node78->node7 + + + + + +node78->node21 + + + + + +node78->node32 + + + + + +node78->node74 + + + + + +node79 + +tracer.cpp + + + +node79->node4 + + + + + +node79->node8 + + + + + +node79->node10 + + + + + +node79->node15 + + + + + +node79->node21 + + + + + +node79->node31 + + + + + +node79->node34 + + + + + +node79->node36 + + + + + +node79->node40 + + + + + +node79->node42 + + + + + +node79->node56 + + + + + +node79->node60 + + + + + +node79->node77 + + + + + +node79->node87 + + + + + +node80 + +default_http_client_curl.cpp + + + +node80->node25 + + + + + +node80->node37 + + + + + +node81->node13 + + + + + +node81->node32 + + + + + +node82 + +clock.cpp + + + +node82->node35 + + + + + +node83->node23 + + + + + +node84 + +collector_response.cpp + + + +node84->node54 + + + + + +node86 + +limiter.cpp + + + +node86->node14 + + + + + +node88 + +error.cpp + + + +node88->node32 + + + + + +node89->node13 + + + + + +node89->node18 + + + + + +node89->node74 + + + + + +node90->node36 + + + + + +node91 + +tags.cpp + + + +node91->node10 + + + + + +node91->node42 + + + + + +node92 + +trace_segment.cpp + + + +node92->node4 + + + + + +node92->node5 + + + + + +node92->node8 + + + + + +node92->node10 + + + + + +node92->node21 + + + + + +node92->node32 + + + + + +node92->node34 + + + + + +node92->node36 + + + + + +node92->node50 + + + + + +node92->node54 + + + + + +node92->node56 + + + + + +node92->node71 + + + + + +node93 + +span_sampler_config.cpp + + + +node93->node7 + + + + + +node93->node13 + + + + + +node93->node36 + + + + + +node93->node61 + + + + + +node93->node73 + + + + + diff --git a/ownership.dot b/doc/ownership.dot similarity index 100% rename from ownership.dot rename to doc/ownership.dot diff --git a/ownership.svg b/doc/ownership.svg similarity index 100% rename from ownership.svg rename to doc/ownership.svg diff --git a/example/hasher.cpp b/example/hasher.cpp index 9edfd8fa..b39ea1e0 100644 --- a/example/hasher.cpp +++ b/example/hasher.cpp @@ -10,7 +10,6 @@ // canonical format. Produce a trace whose structure reflects the directory // structure. -#include #include #include #include diff --git a/includes.dot b/includes.dot deleted file mode 100644 index e69de29b..00000000 diff --git a/includes.svg b/includes.svg deleted file mode 100644 index d43b7f1d..00000000 --- a/includes.svg +++ /dev/null @@ -1,1633 +0,0 @@ - - - - - - -G - - - -node0 - -rate.cpp - - - -node18 - -rate.h - - - -node0->node18 - - - - - -node1 - -span_data.cpp - - - -node11 - -tags.h - - - -node1->node11 - - - - - -node20 - -span_data.h - - - -node1->node20 - - - - - -node32 - -error.h - - - -node1->node32 - - - - - -node38 - -span_defaults.h - - - -node1->node38 - - - - - -node54 - -msgpack.h - - - -node1->node54 - - - - - -node60 - -span_config.h - - - -node1->node60 - - - - - -node2 - -threaded_event_scheduler.cpp - - - -node40 - -threaded_event_scheduler.h - - - -node2->node40 - - - - - -node3 - -trace_segment.h - - - -node13 - -expected.h - - - -node3->node13 - - - - - -node21 - -sampling_decision.h - - - -node3->node21 - - - - - -node83 - -propagation_styles.h - - - -node3->node83 - - - - - -node4 - -default_http_client_null.cpp - - - -node25 - -default_http_client.h - - - -node4->node25 - - - - - -node5 - -dict_writer.h - - - -node6 - -tag_propagation.cpp - - - -node6->node32 - - - - - -node34 - -tag_propagation.h - - - -node6->node34 - - - - - -node7 - -json.hpp - - - -node8 - -span_sampler.h - - - -node14 - -limiter.h - - - -node8->node14 - - - - - -node8->node21 - - - - - -node36 - -clock.h - - - -node8->node36 - - - - - -node73 - -span_sampler_config.h - - - -node8->node73 - - - - - -node9 - -dict_reader.cpp - - - -node75 - -dict_reader.h - - - -node9->node75 - - - - - -node10 - -tracer_config.h - - - -node10->node13 - - - - - -node22 - -datadog_agent_config.h - - - -node10->node22 - - - - - -node10->node32 - - - - - -node10->node38 - - - - - -node10->node73 - - - - - -node10->node83 - - - - - -node86 - -trace_sampler_config.h - - - -node10->node86 - - - - - -node12 - -curl/curl.h - - - -node13->node32 - - - - - -node14->node18 - - - - - -node14->node36 - - - - - -node15 - -span.h - - - -node15->node32 - - - - - -node15->node36 - - - - - -node16 - -sampling_mechanism.cpp - - - -node23 - -sampling_mechanism.h - - - -node16->node23 - - - - - -node17 - -logger.cpp - - - -node17->node32 - - - - - -node35 - -logger.h - - - -node17->node35 - - - - - -node18->node13 - - - - - -node19 - -sampling_util.h - - - -node19->node18 - - - - - -node20->node13 - - - - - -node20->node36 - - - - - -node21->node18 - - - - - -node21->node23 - - - - - -node22->node13 - - - - - -node78 - -http_client.h - - - -node22->node78 - - - - - -node24 - -msgpack.cpp - - - -node24->node54 - - - - - -node26 - -sampling_util.cpp - - - -node26->node19 - - - - - -node27 - -datadog_agent_config.cpp - - - -node27->node22 - - - - - -node27->node25 - - - - - -node27->node40 - - - - - -node59 - -environment.h - - - -node27->node59 - - - - - -node28 - -span.cpp - - - -node28->node3 - - - - - -node28->node5 - - - - - -node28->node11 - - - - - -node28->node15 - - - - - -node28->node20 - - - - - -node29 - -event_scheduler.cpp - - - -node33 - -event_scheduler.h - - - -node29->node33 - - - - - -node30 - -json_fwd.hpp - - - -node31 - -datadog_agent.h - - - -node31->node33 - - - - - -node31->node36 - - - - - -node50 - -collector.h - - - -node31->node50 - - - - - -node31->node78 - - - - - -node33->node32 - - - - - -node34->node13 - - - - - -node37 - -curl.h - - - -node37->node5 - - - - - -node37->node12 - - - - - -node37->node35 - - - - - -node37->node75 - - - - - -node37->node78 - - - - - -node39 - -span_defaults.cpp - - - -node39->node38 - - - - - -node40->node33 - - - - - -node41 - -tracer.h - - - -node41->node10 - - - - - -node41->node13 - - - - - -node41->node15 - - - - - -node41->node32 - - - - - -node41->node36 - - - - - -node64 - -id_generator.h - - - -node41->node64 - - - - - -node42 - -parse_util.h - - - -node42->node13 - - - - - -node68 - -charconv - - - -node42->node68 - - - - - -node43 - -expected.cpp - - - -node43->node13 - - - - - -node44 - -collector.cpp - - - -node44->node50 - - - - - -node45 - -id_generator.cpp - - - -node45->node64 - - - - - -node46 - -sampling_decision.cpp - - - -node46->node21 - - - - - -node47 - -trace_sampler.cpp - - - -node47->node19 - - - - - -node47->node20 - - - - - -node47->node21 - - - - - -node53 - -collector_response.h - - - -node47->node53 - - - - - -node55 - -trace_sampler.h - - - -node47->node55 - - - - - -node82 - -sampling_priority.h - - - -node47->node82 - - - - - -node48 - -sampling_priority.cpp - - - -node48->node82 - - - - - -node49 - -span_sampler.cpp - - - -node49->node8 - - - - - -node49->node19 - - - - - -node49->node20 - - - - - -node49->node23 - - - - - -node49->node82 - - - - - -node50->node13 - - - - - -node51 - -null_collector.cpp - - - -node69 - -null_collector.h - - - -node51->node69 - - - - - -node52 - -cerr_logger.cpp - - - -node87 - -cerr_logger.h - - - -node52->node87 - - - - - -node53->node18 - - - - - -node55->node14 - - - - - -node55->node18 - - - - - -node55->node36 - - - - - -node55->node86 - - - - - -node56 - -span_config.cpp - - - -node56->node60 - - - - - -node57 - -dict_writer.cpp - - - -node57->node5 - - - - - -node58 - -trace_sampler_config.cpp - - - -node58->node7 - - - - - -node58->node59 - - - - - -node58->node86 - - - - - -node60->node36 - - - - - -node61 - -datadog_agent.cpp - - - -node61->node5 - - - - - -node61->node7 - - - - - -node61->node20 - - - - - -node61->node22 - - - - - -node61->node31 - - - - - -node61->node35 - - - - - -node61->node53 - - - - - -node61->node54 - - - - - -node61->node55 - - - - - -node70 - -version.h - - - -node61->node70 - - - - - -node62 - -winsock.h - - - -node63 - -environment.cpp - - - -node63->node59 - - - - - -node65 - -tracer_config.cpp - - - -node65->node10 - - - - - -node65->node31 - - - - - -node65->node59 - - - - - -node65->node69 - - - - - -node65->node87 - - - - - -node66 - -parse_util.cpp - - - -node66->node42 - - - - - -node67 - -http_client.cpp - - - -node67->node78 - - - - - -node69->node50 - - - - - -node71 - -version.cpp - - - -node71->node70 - - - - - -node72 - -span_matcher.h - - - -node72->node13 - - - - - -node72->node30 - - - - - -node73->node13 - - - - - -node73->node18 - - - - - -node73->node72 - - - - - -node74 - -propagation_styles.cpp - - - -node74->node83 - - - - - -node76 - -span_matcher.cpp - - - -node76->node7 - - - - - -node76->node20 - - - - - -node76->node32 - - - - - -node76->node72 - - - - - -node77 - -default_http_client_curl.cpp - - - -node77->node25 - - - - - -node77->node37 - - - - - -node78->node13 - - - - - -node78->node32 - - - - - -node79 - -tracer.cpp - - - -node79->node3 - - - - - -node79->node8 - - - - - -node79->node11 - - - - - -node79->node15 - - - - - -node79->node20 - - - - - -node79->node31 - - - - - -node79->node34 - - - - - -node79->node35 - - - - - -node79->node41 - - - - - -node79->node42 - - - - - -node79->node55 - - - - - -node79->node60 - - - - - -node79->node62 - - - - - -node79->node75 - - - - - -node80 - -clock.cpp - - - -node80->node36 - - - - - -node81 - -collector_response.cpp - - - -node81->node53 - - - - - -node82->node23 - - - - - -node84 - -limiter.cpp - - - -node84->node14 - - - - - -node85 - -error.cpp - - - -node85->node32 - - - - - -node86->node13 - - - - - -node86->node18 - - - - - -node86->node72 - - - - - -node87->node35 - - - - - -node88 - -tags.cpp - - - -node88->node11 - - - - - -node89 - -trace_segment.cpp - - - -node89->node3 - - - - - -node89->node5 - - - - - -node89->node8 - - - - - -node89->node11 - - - - - -node89->node20 - - - - - -node89->node32 - - - - - -node89->node34 - - - - - -node89->node35 - - - - - -node89->node50 - - - - - -node89->node53 - - - - - -node89->node55 - - - - - -node90 - -span_sampler_config.cpp - - - -node90->node7 - - - - - -node90->node13 - - - - - -node90->node35 - - - - - -node90->node59 - - - - - -node90->node73 - - - - - diff --git a/src/datadog/curl.cpp b/src/datadog/curl.cpp index 01329917..1575d73f 100644 --- a/src/datadog/curl.cpp +++ b/src/datadog/curl.cpp @@ -1,9 +1,105 @@ #include "curl.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dict_reader.h" +#include "dict_writer.h" +#include "http_client.h" +#include "logger.h" #include "parse_util.h" namespace datadog { namespace tracing { + +using ErrorHandler = HTTPClient::ErrorHandler; +using HeadersSetter = HTTPClient::HeadersSetter; +using ResponseHandler = HTTPClient::ResponseHandler; +using URL = HTTPClient::URL; + +class CurlImpl { + std::mutex mutex_; + std::shared_ptr logger_; + CURLM *multi_handle_; + std::unordered_set request_handles_; + std::list new_handles_; + bool shutting_down_; + int num_active_handles_; + std::condition_variable no_requests_; + std::thread event_loop_; + + struct Request { + curl_slist *request_headers = nullptr; + std::string request_body; + ResponseHandler on_response; + ErrorHandler on_error; + char error_buffer[CURL_ERROR_SIZE] = ""; + std::unordered_map response_headers_lower; + std::string response_body; + + ~Request(); + }; + + class HeaderWriter : public DictWriter { + curl_slist *list_ = nullptr; + std::string buffer_; + + public: + ~HeaderWriter(); + curl_slist *release(); + void set(std::string_view key, std::string_view value) override; + }; + + class HeaderReader : public DictReader { + std::unordered_map *response_headers_lower_; + mutable std::string buffer_; + + public: + explicit HeaderReader( + std::unordered_map *response_headers_lower); + std::optional lookup(std::string_view key) const override; + void visit( + const std::function + &visitor) const override; + }; + + void run(); + void handle_message(const CURLMsg &); + CURLcode log_on_error(CURLcode result); + CURLMcode log_on_error(CURLMcode result); + + static std::size_t on_read_header(char *data, std::size_t, std::size_t length, + void *user_data); + static std::size_t on_read_body(char *data, std::size_t, std::size_t length, + void *user_data); + static bool is_non_whitespace(unsigned char); + static char to_lower(unsigned char); + static std::string_view trim(std::string_view); + + public: + explicit CurlImpl(const std::shared_ptr &logger); + ~CurlImpl(); + + Expected post(const URL &url, HeadersSetter set_headers, + std::string body, ResponseHandler on_response, + ErrorHandler on_error); + + void drain(std::chrono::steady_clock::time_point deadline); +}; + namespace { void throw_on_error(CURLcode result) { @@ -15,6 +111,21 @@ void throw_on_error(CURLcode result) { } // namespace Curl::Curl(const std::shared_ptr &logger) + : impl_(new CurlImpl{logger}) {} + +Curl::~Curl() { delete impl_; } + +Expected Curl::post(const URL &url, HeadersSetter set_headers, + std::string body, ResponseHandler on_response, + ErrorHandler on_error) { + return impl_->post(url, set_headers, body, on_response, on_error); +} + +void Curl::drain(std::chrono::steady_clock::time_point deadline) { + impl_->drain(deadline); +} + +CurlImpl::CurlImpl(const std::shared_ptr &logger) : logger_(logger), shutting_down_(false), num_active_handles_(0) { curl_global_init(CURL_GLOBAL_ALL); multi_handle_ = curl_multi_init(); @@ -41,7 +152,7 @@ Curl::Curl(const std::shared_ptr &logger) } } -Curl::~Curl() { +CurlImpl::~CurlImpl() { if (multi_handle_ == nullptr) { // We're not running; nothing to shut down. return; @@ -55,9 +166,10 @@ Curl::~Curl() { event_loop_.join(); } -Expected Curl::post(const HTTPClient::URL &url, HeadersSetter set_headers, - std::string body, ResponseHandler on_response, - ErrorHandler on_error) try { +Expected CurlImpl::post(const HTTPClient::URL &url, + HeadersSetter set_headers, std::string body, + ResponseHandler on_response, + ErrorHandler on_error) try { if (multi_handle_ == nullptr) { return Error{Error::CURL_HTTP_CLIENT_NOT_RUNNING, "Unable to send request via libcurl because the HTTP client " @@ -136,15 +248,15 @@ Expected Curl::post(const HTTPClient::URL &url, HeadersSetter set_headers, return Error{Error::CURL_REQUEST_SETUP_FAILED, curl_easy_strerror(error)}; } -void Curl::drain(std::chrono::steady_clock::time_point deadline) { +void CurlImpl::drain(std::chrono::steady_clock::time_point deadline) { std::unique_lock lock(mutex_); no_requests_.wait_until(lock, deadline, [this]() { return num_active_handles_ == 0 && new_handles_.empty(); }); } -std::size_t Curl::on_read_header(char *data, std::size_t, std::size_t length, - void *user_data) { +std::size_t CurlImpl::on_read_header(char *data, std::size_t, + std::size_t length, void *user_data) { const auto request = static_cast(user_data); // The idea is: // @@ -179,18 +291,18 @@ std::size_t Curl::on_read_header(char *data, std::size_t, std::size_t length, return length; } -bool Curl::is_non_whitespace(unsigned char ch) { return !std::isspace(ch); } +bool CurlImpl::is_non_whitespace(unsigned char ch) { return !std::isspace(ch); } -char Curl::to_lower(unsigned char ch) { return std::tolower(ch); } +char CurlImpl::to_lower(unsigned char ch) { return std::tolower(ch); } -std::size_t Curl::on_read_body(char *data, std::size_t, std::size_t length, - void *user_data) { +std::size_t CurlImpl::on_read_body(char *data, std::size_t, std::size_t length, + void *user_data) { const auto request = static_cast(user_data); request->response_body.append(data, length); return length; } -CURLcode Curl::log_on_error(CURLcode result) { +CURLcode CurlImpl::log_on_error(CURLcode result) { if (result != CURLE_OK) { logger_->log_error( Error{Error::CURL_HTTP_CLIENT_ERROR, curl_easy_strerror(result)}); @@ -198,7 +310,7 @@ CURLcode Curl::log_on_error(CURLcode result) { return result; } -CURLMcode Curl::log_on_error(CURLMcode result) { +CURLMcode CurlImpl::log_on_error(CURLMcode result) { if (result != CURLM_OK) { logger_->log_error( Error{Error::CURL_HTTP_CLIENT_ERROR, curl_multi_strerror(result)}); @@ -206,7 +318,7 @@ CURLMcode Curl::log_on_error(CURLMcode result) { return result; } -void Curl::run() { +void CurlImpl::run() { int num_messages_remaining; CURLMsg *message; std::unique_lock lock(mutex_); @@ -258,7 +370,7 @@ void Curl::run() { curl_global_cleanup(); } -void Curl::handle_message(const CURLMsg &message) { +void CurlImpl::handle_message(const CURLMsg &message) { if (message.msg != CURLMSG_DONE) { return; } @@ -299,17 +411,17 @@ void Curl::handle_message(const CURLMsg &message) { delete &request; } -Curl::Request::~Request() { curl_slist_free_all(request_headers); } +CurlImpl::Request::~Request() { curl_slist_free_all(request_headers); } -Curl::HeaderWriter::~HeaderWriter() { curl_slist_free_all(list_); } +CurlImpl::HeaderWriter::~HeaderWriter() { curl_slist_free_all(list_); } -curl_slist *Curl::HeaderWriter::release() { +curl_slist *CurlImpl::HeaderWriter::release() { auto list = list_; list_ = nullptr; return list; } -void Curl::HeaderWriter::set(std::string_view key, std::string_view value) { +void CurlImpl::HeaderWriter::set(std::string_view key, std::string_view value) { buffer_.clear(); buffer_ += key; buffer_ += ": "; @@ -318,11 +430,11 @@ void Curl::HeaderWriter::set(std::string_view key, std::string_view value) { list_ = curl_slist_append(list_, buffer_.c_str()); } -Curl::HeaderReader::HeaderReader( +CurlImpl::HeaderReader::HeaderReader( std::unordered_map *response_headers_lower) : response_headers_lower_(response_headers_lower) {} -std::optional Curl::HeaderReader::lookup( +std::optional CurlImpl::HeaderReader::lookup( std::string_view key) const { buffer_.clear(); std::transform(key.begin(), key.end(), std::back_inserter(buffer_), @@ -335,7 +447,7 @@ std::optional Curl::HeaderReader::lookup( return found->second; } -void Curl::HeaderReader::visit( +void CurlImpl::HeaderReader::visit( const std::function &visitor) const { for (const auto &[key, value] : *response_headers_lower_) { diff --git a/src/datadog/curl.h b/src/datadog/curl.h index ec8f8a74..632c55f1 100644 --- a/src/datadog/curl.h +++ b/src/datadog/curl.h @@ -1,98 +1,31 @@ #pragma once -#include - -#include -#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include -#include "dict_reader.h" -#include "dict_writer.h" #include "http_client.h" -#include "logger.h" namespace datadog { namespace tracing { -class Curl : public HTTPClient { - std::mutex mutex_; - std::shared_ptr logger_; - CURLM *multi_handle_; - std::unordered_set request_handles_; - std::list new_handles_; - bool shutting_down_; - int num_active_handles_; - std::condition_variable no_requests_; - std::thread event_loop_; - - struct Request { - curl_slist *request_headers = nullptr; - std::string request_body; - ResponseHandler on_response; - ErrorHandler on_error; - char error_buffer[CURL_ERROR_SIZE] = ""; - std::unordered_map response_headers_lower; - std::string response_body; - - ~Request(); - }; - - class HeaderWriter : public DictWriter { - curl_slist *list_ = nullptr; - std::string buffer_; - - public: - ~HeaderWriter(); - curl_slist *release(); - virtual void set(std::string_view key, std::string_view value) override; - }; +class CurlImpl; +class Logger; - class HeaderReader : public DictReader { - std::unordered_map *response_headers_lower_; - mutable std::string buffer_; - - public: - explicit HeaderReader( - std::unordered_map *response_headers_lower); - virtual std::optional lookup( - std::string_view key) const override; - virtual void visit( - const std::function - &visitor) const override; - }; - - void run(); - void handle_message(const CURLMsg &); - CURLcode log_on_error(CURLcode result); - CURLMcode log_on_error(CURLMcode result); - - static std::size_t on_read_header(char *data, std::size_t, std::size_t length, - void *user_data); - static std::size_t on_read_body(char *data, std::size_t, std::size_t length, - void *user_data); - static bool is_non_whitespace(unsigned char); - static char to_lower(unsigned char); - static std::string_view trim(std::string_view); +class Curl : public HTTPClient { + CurlImpl* impl_; public: - explicit Curl(const std::shared_ptr &logger); + explicit Curl(const std::shared_ptr& logger); ~Curl(); - virtual Expected post(const URL &url, HeadersSetter set_headers, - std::string body, ResponseHandler on_response, - ErrorHandler on_error) override; + Curl(const Curl&) = delete; + + Expected post(const URL& url, HeadersSetter set_headers, + std::string body, ResponseHandler on_response, + ErrorHandler on_error) override; - virtual void drain(std::chrono::steady_clock::time_point deadline) override; + void drain(std::chrono::steady_clock::time_point deadline) override; }; } // namespace tracing diff --git a/src/datadog/msgpack.h b/src/datadog/msgpack.h index 212350cf..812a6c57 100644 --- a/src/datadog/msgpack.h +++ b/src/datadog/msgpack.h @@ -121,7 +121,10 @@ template Expected pack_map(std::string& buffer, Key&& key, PackValue&& pack_value, Rest&&... rest) { Expected result; - result = pack_map(buffer, 1 + sizeof...(rest)); + static_assert( + sizeof...(rest) % 2 == 0, + "pack_map must receive an even number of arguments after the first."); + result = pack_map(buffer, 1 + sizeof...(rest) / 2); if (!result) { return result; } diff --git a/test/test_tracer_config.cpp b/test/test_tracer_config.cpp index 1be6f7a7..31ac9c1a 100644 --- a/test/test_tracer_config.cpp +++ b/test/test_tracer_config.cpp @@ -964,24 +964,6 @@ TEST_CASE("TracerConfig::span_sampler") { REQUIRE(finalized.error().code == Error::SPAN_SAMPLING_RULES_FILE_IO); } - SECTION("unable to read") { - SomewhatSecureTemporaryFile file; - REQUIRE(file.is_open()); - file << "[]"; - file.close(); - // We can't read it anymore. This doesn't actually cover the call to - // `::read` (i.e. `std::filebuf::[...]`) failing, but getting that to - // fail after the file has already been opened for reading is too - // tricky. - std::filesystem::permissions(file.path(), - std::filesystem::perms(0200)); - const EnvGuard guard{"DD_SPAN_SAMPLING_RULES_FILE", - file.path().string()}; - auto finalized = finalize_config(config); - REQUIRE(!finalized); - REQUIRE(finalized.error().code == Error::SPAN_SAMPLING_RULES_FILE_IO); - } - SECTION("unable to parse") { SomewhatSecureTemporaryFile file; REQUIRE(file.is_open());