diff --git a/.circleci/README.md b/.circleci/README.md index cc703ab9..85c7e797 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -13,7 +13,7 @@ The following jobs are defined: - Based on the `toolchain` parameter, the build will use either g++ or clang++. - Based on the `sanitize` parameter, the build might use [AddressSanitizer and - MemorySanitizer][3]. + UndefinedBehaviorSanitizer][3]. [1]: https://bazel.build/ [2]: https://cmake.org/ diff --git a/BUILD.bazel b/BUILD.bazel index 5573b39b..088228a5 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -26,7 +26,7 @@ cc_library( "src/datadog/null_collector.cpp", "src/datadog/optional.cpp", "src/datadog/parse_util.cpp", - "src/datadog/propagation_styles.cpp", + "src/datadog/propagation_style.cpp", "src/datadog/rate.cpp", "src/datadog/sampling_decision.cpp", "src/datadog/sampling_mechanism.cpp", @@ -77,7 +77,7 @@ cc_library( "src/datadog/null_collector.h", "src/datadog/optional.h", "src/datadog/parse_util.h", - "src/datadog/propagation_styles.h", + "src/datadog/propagation_style.h", "src/datadog/rate.h", "src/datadog/sampling_decision.h", "src/datadog/sampling_mechanism.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index ffb0ce6b..07aaaab9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ project(dd-trace-cpp) option(BUILD_COVERAGE "Build code with code coverage profiling instrumentation" OFF) option(BUILD_EXAMPLE "Build the example program (example/)" OFF) +option(BUILD_TESTING "Build the unit tests (test/)" OFF) +option(SANITIZE "Build with address sanitizer and undefined behavior sanitizer" OFF) set(CMAKE_BUILD_TYPE "RelWithDebInfo") set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -78,7 +80,7 @@ target_sources(dd_trace_cpp PRIVATE src/datadog/null_collector.cpp src/datadog/optional.cpp src/datadog/parse_util.cpp - src/datadog/propagation_styles.cpp + src/datadog/propagation_style.cpp src/datadog/rate.cpp src/datadog/sampling_decision.cpp src/datadog/sampling_mechanism.cpp @@ -135,7 +137,7 @@ target_sources(dd_trace_cpp PUBLIC src/datadog/null_collector.h src/datadog/optional.h src/datadog/parse_util.h - src/datadog/propagation_styles.h + src/datadog/propagation_style.h src/datadog/rate.h src/datadog/sampling_decision.h src/datadog/sampling_mechanism.h diff --git a/doc/includes.dot b/doc/includes.dot index 2db29b94..1725ee7f 100644 --- a/doc/includes.dot +++ b/doc/includes.dot @@ -1,318 +1,367 @@ digraph G { - node0 [label="threaded_event_scheduler.cpp"]; - node1 [label="rate.cpp"]; - node2 [label="span_data.cpp"]; + node0 [label="rate.cpp"]; + node1 [label="span_data.cpp"]; + node2 [label="threaded_event_scheduler.cpp"]; node3 [label="default_http_client_null.cpp"]; node4 [label="trace_segment.h"]; - node5 [label="dict_writer.h"]; - node6 [label="tag_propagation.cpp"]; + node5 [label="tag_propagation.cpp"]; + node6 [label="dict_writer.h"]; node7 [label="json.hpp"]; - node8 [label="span_sampler.h"]; - node9 [label="dict_reader.cpp"]; - node10 [label="tracer_config.h"]; + node8 [label="string_view.h"]; + node9 [label="span_sampler.h"]; + node10 [label="dict_reader.cpp"]; node11 [label="tags.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="span_data.h"]; - node21 [label="datadog_agent_config.h"]; - node22 [label="sampling_decision.h"]; - node23 [label="sampling_mechanism.h"]; - node24 [label="msgpack.cpp"]; - node25 [label="default_http_client.h"]; - node26 [label="datadog_agent_config.cpp"]; - node27 [label="sampling_util.cpp"]; - node28 [label="event_scheduler.cpp"]; - node29 [label="span.cpp"]; - node30 [label="json_fwd.hpp"]; - node31 [label="datadog_agent.h"]; - node32 [label="error.h"]; - node33 [label="event_scheduler.h"]; - node34 [label="tag_propagation.h"]; - node35 [label="logger.h"]; - node36 [label="clock.h"]; - node37 [label="span_defaults.h"]; - node38 [label="curl.h"]; - node39 [label="span_defaults.cpp"]; - node40 [label="threaded_event_scheduler.h"]; - node41 [label="tracer.h"]; - node42 [label="parse_util.h"]; - node43 [label="expected.cpp"]; - node44 [label="collector.cpp"]; - node45 [label="id_generator.cpp"]; - node46 [label="trace_sampler.cpp"]; - node47 [label="sampling_decision.cpp"]; - node48 [label="sampling_priority.cpp"]; - node49 [label="span_sampler.cpp"]; - node50 [label="collector.h"]; - node51 [label="curl.cpp"]; - node52 [label="collector_response.h"]; - node53 [label="cerr_logger.cpp"]; - node54 [label="null_collector.cpp"]; - 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="environment.h"]; - node61 [label="span_config.h"]; - node62 [label="datadog_agent.cpp"]; - node63 [label="winsock.h"]; - node64 [label="id_generator.h"]; - node65 [label="environment.cpp"]; - node66 [label="tracer_config.cpp"]; - node67 [label="net_util.cpp"]; - node68 [label="parse_util.cpp"]; - node69 [label="http_client.cpp"]; - node70 [label="charconv"]; - node71 [label="null_collector.h"]; - node72 [label="version.h"]; - node73 [label="version.cpp"]; - node74 [label="span_matcher.h"]; - node75 [label="span_sampler_config.h"]; - node76 [label="propagation_styles.cpp"]; - node77 [label="dict_reader.h"]; - node78 [label="span_matcher.cpp"]; - node79 [label="default_http_client_curl.cpp"]; - node80 [label="tracer.cpp"]; - node81 [label="http_client.h"]; - node82 [label="clock.cpp"]; - node83 [label="collector_response.cpp"]; - node84 [label="sampling_priority.h"]; - 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"]; + node12 [label="tracer_config.h"]; + node13 [label="curl/curl.h"]; + node14 [label="expected.h"]; + node15 [label="limiter.h"]; + node16 [label="optional.cpp"]; + node17 [label="span.h"]; + node18 [label="sampling_mechanism.cpp"]; + node19 [label="logger.cpp"]; + node20 [label="rate.h"]; + node21 [label="sampling_util.h"]; + node22 [label="string_view.cpp"]; + node23 [label="sampling_decision.h"]; + node24 [label="span_data.h"]; + node25 [label="datadog_agent_config.h"]; + node26 [label="sampling_mechanism.h"]; + node27 [label="glob.h"]; + node28 [label="msgpack.cpp"]; + node29 [label="absl/types/optional.h"]; + node30 [label="default_http_client.h"]; + node31 [label="sampling_util.cpp"]; + node32 [label="datadog_agent_config.cpp"]; + node33 [label="span.cpp"]; + node34 [label="event_scheduler.cpp"]; + node35 [label="json_fwd.hpp"]; + node36 [label="datadog_agent.h"]; + node37 [label="propagation_style.cpp"]; + node38 [label="error.h"]; + node39 [label="event_scheduler.h"]; + node40 [label="tag_propagation.h"]; + node41 [label="clock.h"]; + node42 [label="logger.h"]; + node43 [label="span_defaults.h"]; + node44 [label="curl.h"]; + node45 [label="span_defaults.cpp"]; + node46 [label="threaded_event_scheduler.h"]; + node47 [label="tracer.h"]; + node48 [label="parse_util.h"]; + node49 [label="expected.cpp"]; + node50 [label="collector.cpp"]; + node51 [label="id_generator.cpp"]; + node52 [label="trace_sampler.cpp"]; + node53 [label="sampling_decision.cpp"]; + node54 [label="sampling_priority.cpp"]; + node55 [label="span_sampler.cpp"]; + node56 [label="collector.h"]; + node57 [label="curl.cpp"]; + node58 [label="null_collector.cpp"]; + node59 [label="cerr_logger.cpp"]; + node60 [label="collector_response.h"]; + node61 [label="msgpack.h"]; + node62 [label="trace_sampler.h"]; + node63 [label="span_config.cpp"]; + node64 [label="propagation_style.h"]; + node65 [label="dict_writer.cpp"]; + node66 [label="trace_sampler_config.cpp"]; + node67 [label="environment.h"]; + node68 [label="span_config.h"]; + node69 [label="datadog_agent.cpp"]; + node70 [label="winsock.h"]; + node71 [label="environment.cpp"]; + node72 [label="id_generator.h"]; + node73 [label="tracer_config.cpp"]; + node74 [label="net_util.cpp"]; + node75 [label="parse_util.cpp"]; + node76 [label="http_client.cpp"]; + node77 [label="optional.h"]; + node78 [label="null_collector.h"]; + node79 [label="charconv"]; + node80 [label="version.h"]; + node81 [label="span_sampler_config.h"]; + node82 [label="span_matcher.h"]; + node83 [label="version.cpp"]; + node84 [label="dict_reader.h"]; + node85 [label="span_matcher.cpp"]; + node86 [label="tracer.cpp"]; + node87 [label="default_http_client_curl.cpp"]; + node88 [label="http_client.h"]; + node89 [label="clock.cpp"]; + node90 [label="collector_response.cpp"]; + node91 [label="sampling_priority.h"]; + node92 [label="net_util.h"]; + node93 [label="limiter.cpp"]; + node94 [label="error.cpp"]; + node95 [label="absl/strings/string_view.h"]; + node96 [label="trace_sampler_config.h"]; + node97 [label="tags.cpp"]; + node98 [label="cerr_logger.h"]; + node99 [label="trace_segment.cpp"]; + node100 [label="span_sampler_config.cpp"]; subgraph U { edge [dir=none]; } subgraph D { - node0 -> node7 []; - node0 -> node40 []; - node1 -> node18 []; - node2 -> node37 []; - node2 -> node61 []; - node2 -> node20 []; - node2 -> node55 []; - node2 -> node11 []; - node2 -> node32 []; - node3 -> node25 []; - node4 -> node85 []; - node4 -> node22 []; - node4 -> node13 []; - node6 -> node34 []; - node6 -> node42 []; - node6 -> node32 []; - node8 -> node36 []; - node8 -> node75 []; - node8 -> node22 []; - node8 -> node14 []; - node8 -> node30 []; - node9 -> node77 []; - node10 -> node75 []; - node10 -> node21 []; - node10 -> node89 []; - node10 -> node13 []; - node10 -> node32 []; - node10 -> node85 []; - node10 -> node37 []; - node13 -> node32 []; - node14 -> node36 []; - node14 -> node18 []; - node15 -> node36 []; - node15 -> node64 []; - node15 -> node32 []; - node16 -> node23 []; - node17 -> node35 []; - node17 -> node32 []; - node18 -> node13 []; - node19 -> node18 []; - node20 -> node36 []; - node20 -> node13 []; - node21 -> node13 []; - node21 -> node81 []; - node22 -> node23 []; - node22 -> node18 []; - node24 -> node55 []; - node24 -> node32 []; - node26 -> node42 []; - node26 -> node21 []; - node26 -> node25 []; - node26 -> node60 []; - node26 -> node40 []; - node27 -> node19 []; - node28 -> node33 []; - node29 -> node4 []; - node29 -> node61 []; - node29 -> node5 []; - node29 -> node20 []; - node29 -> node15 []; - node29 -> node11 []; - node31 -> node36 []; - node31 -> node50 []; - node31 -> node81 []; - node31 -> node33 []; - node33 -> node30 []; - node33 -> node32 []; - node34 -> node13 []; - node37 -> node30 []; - node38 -> node81 []; - node38 -> node30 []; - node39 -> node37 []; - node39 -> node7 []; - node40 -> node33 []; - node41 -> node36 []; - node41 -> node64 []; - node41 -> node15 []; - node41 -> node32 []; - node41 -> node13 []; - node41 -> node10 []; - node42 -> node13 []; - node43 -> node13 []; - node44 -> node50 []; - node45 -> node64 []; - node46 -> node19 []; - node46 -> node56 []; - node46 -> node84 []; - node46 -> node52 []; - node46 -> node20 []; - node46 -> node22 []; - node46 -> node7 []; - node47 -> node22 []; - node48 -> node84 []; - node49 -> node23 []; - node49 -> node19 []; - node49 -> node84 []; - node49 -> node7 []; - node49 -> node8 []; - node49 -> node20 []; - node50 -> node13 []; - node50 -> node30 []; - node51 -> node35 []; - node51 -> node7 []; - node51 -> node38 []; - node51 -> node5 []; - node51 -> node42 []; - node51 -> node12 []; - node51 -> node81 []; - node51 -> node77 []; - node52 -> node18 []; - node53 -> node90 []; - node54 -> node7 []; - node54 -> node71 []; - node55 -> node13 []; - node56 -> node36 []; - node56 -> node89 []; - node56 -> node18 []; + node0 -> node20 []; + node1 -> node43 []; + node1 -> node68 []; + node1 -> node8 []; + node1 -> node24 []; + node1 -> node61 []; + node1 -> node11 []; + node1 -> node38 []; + node2 -> node7 []; + node2 -> node46 []; + node3 -> node30 []; + node4 -> node64 []; + node4 -> node23 []; + node4 -> node14 []; + node4 -> node77 []; + node5 -> node40 []; + node5 -> node48 []; + node5 -> node38 []; + node6 -> node8 []; + node8 -> node95 []; + node9 -> node41 []; + node9 -> node81 []; + node9 -> node23 []; + node9 -> node15 []; + node9 -> node35 []; + node10 -> node84 []; + node11 -> node8 []; + node12 -> node43 []; + node12 -> node64 []; + node12 -> node81 []; + node12 -> node25 []; + node12 -> node96 []; + node12 -> node14 []; + node12 -> node38 []; + node14 -> node77 []; + node14 -> node38 []; + node15 -> node41 []; + node15 -> node20 []; + node16 -> node77 []; + node17 -> node41 []; + node17 -> node72 []; + node17 -> node8 []; + node17 -> node77 []; + node17 -> node38 []; + node18 -> node26 []; + node19 -> node42 []; + node19 -> node38 []; + node20 -> node14 []; + node21 -> node20 []; + node22 -> node8 []; + node23 -> node26 []; + node23 -> node20 []; + node23 -> node77 []; + node24 -> node41 []; + node24 -> node14 []; + node24 -> node8 []; + node24 -> node77 []; + node25 -> node14 []; + node25 -> node88 []; + node25 -> node8 []; + node27 -> node8 []; + node28 -> node61 []; + node28 -> node38 []; + node31 -> node21 []; + node32 -> node48 []; + node32 -> node25 []; + node32 -> node30 []; + node32 -> node67 []; + node32 -> node46 []; + node33 -> node4 []; + node33 -> node68 []; + node33 -> node6 []; + node33 -> node24 []; + node33 -> node77 []; + node33 -> node11 []; + node33 -> node8 []; + node33 -> node17 []; + node34 -> node39 []; + node36 -> node41 []; + node36 -> node56 []; + node36 -> node88 []; + node36 -> node39 []; + node37 -> node64 []; + node37 -> node7 []; + node38 -> node8 []; + node39 -> node35 []; + node39 -> node38 []; + node40 -> node14 []; + node40 -> node8 []; + node42 -> node8 []; + node43 -> node35 []; + node44 -> node88 []; + node44 -> node35 []; + node45 -> node43 []; + node45 -> node7 []; + node46 -> node39 []; + node47 -> node41 []; + node47 -> node72 []; + node47 -> node17 []; + node47 -> node77 []; + node47 -> node38 []; + node47 -> node14 []; + node47 -> node12 []; + node48 -> node14 []; + node48 -> node8 []; + node49 -> node14 []; + node50 -> node56 []; + node51 -> node72 []; + node52 -> node21 []; + node52 -> node62 []; + node52 -> node91 []; + node52 -> node60 []; + node52 -> node24 []; + node52 -> node23 []; + node52 -> node7 []; + node53 -> node23 []; + node54 -> node91 []; + node55 -> node26 []; + node55 -> node21 []; + node55 -> node91 []; + node55 -> node7 []; + node55 -> node9 []; + node55 -> node24 []; node56 -> node14 []; - node56 -> node30 []; - node57 -> node61 []; - node58 -> node5 []; - node59 -> node42 []; - node59 -> node89 []; - node59 -> node7 []; - node59 -> node60 []; - node60 -> node30 []; - node61 -> node36 []; - node62 -> node35 []; - node62 -> node21 []; - node62 -> node52 []; - node62 -> node7 []; - node62 -> node72 []; - node62 -> node31 []; - node62 -> node56 []; - node62 -> node5 []; + node56 -> node77 []; + node56 -> node35 []; + node57 -> node42 []; + node57 -> node7 []; + node57 -> node8 []; + node57 -> node44 []; + node57 -> node6 []; + node57 -> node48 []; + node57 -> node13 []; + node57 -> node88 []; + node57 -> node84 []; + node58 -> node7 []; + node58 -> node78 []; + node59 -> node98 []; + node60 -> node20 []; + node60 -> node8 []; + node61 -> node14 []; + node61 -> node8 []; + node62 -> node41 []; + node62 -> node96 []; node62 -> node20 []; - node62 -> node55 []; - node65 -> node7 []; - node65 -> node60 []; - node66 -> node42 []; - node66 -> node90 []; - node66 -> node10 []; - node66 -> node60 []; - node66 -> node71 []; - node66 -> node31 []; - node67 -> node87 []; - node67 -> node63 []; - node68 -> node70 []; - node68 -> node42 []; - node68 -> node32 []; - node69 -> node81 []; - node71 -> node50 []; - node73 -> node72 []; - node74 -> node13 []; - node74 -> node30 []; - node75 -> node13 []; - node75 -> node18 []; - node75 -> node74 []; - node75 -> node30 []; - node76 -> node85 []; - node76 -> node7 []; - node78 -> node7 []; - node78 -> node20 []; - node78 -> node74 []; - node78 -> node32 []; - node79 -> node25 []; - node79 -> node38 []; - node80 -> node4 []; - node80 -> node61 []; - node80 -> node41 []; + node62 -> node15 []; + node62 -> node77 []; + node62 -> node35 []; + node63 -> node68 []; + node64 -> node35 []; + node65 -> node6 []; + node66 -> node48 []; + node66 -> node96 []; + node66 -> node7 []; + node66 -> node67 []; + node67 -> node8 []; + node67 -> node77 []; + node67 -> node35 []; + node68 -> node41 []; + node68 -> node77 []; + node69 -> node42 []; + node69 -> node25 []; + node69 -> node60 []; + node69 -> node7 []; + node69 -> node80 []; + node69 -> node36 []; + node69 -> node62 []; + node69 -> node6 []; + node69 -> node24 []; + node69 -> node61 []; + node71 -> node7 []; + node71 -> node67 []; + node73 -> node48 []; + node73 -> node98 []; + node73 -> node7 []; + node73 -> node12 []; + node73 -> node67 []; + node73 -> node8 []; + node73 -> node78 []; + node73 -> node36 []; + node74 -> node92 []; + node74 -> node70 []; + node75 -> node79 []; + node75 -> node48 []; + node75 -> node38 []; + node76 -> node88 []; + node77 -> node29 []; + node78 -> node56 []; node80 -> node8 []; - node80 -> node31 []; - node80 -> node11 []; - node80 -> node34 []; - node80 -> node35 []; - node80 -> node56 []; - node80 -> node42 []; - node80 -> node7 []; - node80 -> node87 []; - node80 -> node20 []; - node80 -> node77 []; - node80 -> node60 []; - node80 -> node15 []; - node80 -> node72 []; - node81 -> node13 []; - node81 -> node30 []; - node81 -> node32 []; - node82 -> node36 []; - node83 -> node52 []; - node84 -> node23 []; - node85 -> node30 []; - node86 -> node14 []; - node88 -> node32 []; - node89 -> node13 []; - node89 -> node18 []; - node89 -> node74 []; - node89 -> node30 []; - node90 -> node35 []; - node91 -> node42 []; - node91 -> node11 []; - node92 -> node50 []; - node92 -> node52 []; - node92 -> node8 []; - node92 -> node20 []; - node92 -> node34 []; - node92 -> node35 []; - node92 -> node4 []; - node92 -> node70 []; - node92 -> node56 []; - node92 -> node5 []; - node92 -> node11 []; - node92 -> node32 []; - node93 -> node35 []; - node93 -> node75 []; - node93 -> node7 []; - node93 -> node13 []; - node93 -> node60 []; + node81 -> node14 []; + node81 -> node20 []; + node81 -> node82 []; + node81 -> node77 []; + node81 -> node35 []; + node82 -> node14 []; + node82 -> node35 []; + node83 -> node80 []; + node84 -> node8 []; + node84 -> node77 []; + node85 -> node7 []; + node85 -> node24 []; + node85 -> node38 []; + node85 -> node82 []; + node85 -> node77 []; + node86 -> node4 []; + node86 -> node68 []; + node86 -> node47 []; + node86 -> node9 []; + node86 -> node36 []; + node86 -> node11 []; + node86 -> node40 []; + node86 -> node42 []; + node86 -> node62 []; + node86 -> node48 []; + node86 -> node7 []; + node86 -> node92 []; + node86 -> node24 []; + node86 -> node84 []; + node86 -> node67 []; + node86 -> node17 []; + node86 -> node80 []; + node87 -> node30 []; + node87 -> node44 []; + node88 -> node14 []; + node88 -> node38 []; + node88 -> node77 []; + node88 -> node35 []; + node89 -> node41 []; + node90 -> node60 []; + node91 -> node26 []; + node92 -> node77 []; + node93 -> node15 []; + node94 -> node38 []; + node96 -> node14 []; + node96 -> node20 []; + node96 -> node82 []; + node96 -> node77 []; + node96 -> node35 []; + node97 -> node48 []; + node97 -> node11 []; + node98 -> node42 []; + node99 -> node56 []; + node99 -> node60 []; + node99 -> node9 []; + node99 -> node24 []; + node99 -> node77 []; + node99 -> node40 []; + node99 -> node42 []; + node99 -> node4 []; + node99 -> node79 []; + node99 -> node62 []; + node99 -> node6 []; + node99 -> node11 []; + node99 -> node38 []; + node100 -> node42 []; + node100 -> node81 []; + node100 -> node7 []; + node100 -> node14 []; + node100 -> node67 []; } } diff --git a/doc/includes.svg b/doc/includes.svg index ac674744..5e55705b 100644 --- a/doc/includes.svg +++ b/doc/includes.svg @@ -4,1876 +4,2170 @@ - - + + G - + node0 - -threaded_event_scheduler.cpp + +rate.cpp - - -node7 - -json.hpp + + +node20 + +rate.h - + -node0->node7 - - - - - -node40 - -threaded_event_scheduler.h - - - -node0->node40 - - +node0->node20 + + node1 - -rate.cpp + +span_data.cpp - - -node18 - -rate.h - - - -node1->node18 - - + + +node8 + +string_view.h - - -node2 - -span_data.cpp + + +node1->node8 + + node11 - -tags.h - - - -node2->node11 - - + +tags.h - - -node20 - -span_data.h - - - -node2->node20 - - + + +node1->node11 + + - - -node32 - -error.h + + +node24 + +span_data.h - - -node2->node32 - - + + +node1->node24 + + - - -node37 - -span_defaults.h + + +node38 + +error.h - - -node2->node37 - - + + +node1->node38 + + - - -node55 - -msgpack.h + + +node43 + +span_defaults.h - - -node2->node55 - - + + +node1->node43 + + node61 - -span_config.h + +msgpack.h - - -node2->node61 - - + + +node1->node61 + + + + + +node68 + +span_config.h + + + +node1->node68 + + + + + +node2 + +threaded_event_scheduler.cpp + + + +node7 + +json.hpp + + + +node2->node7 + + + + + +node46 + +threaded_event_scheduler.h + + + +node2->node46 + + node3 - -default_http_client_null.cpp + +default_http_client_null.cpp - - -node25 - -default_http_client.h + + +node30 + +default_http_client.h - - -node3->node25 - - + + +node3->node30 + + node4 - -trace_segment.h + +trace_segment.h - - -node13 - -expected.h + + +node14 + +expected.h + + + +node4->node14 + + + + + +node23 + +sampling_decision.h - + -node4->node13 - - +node4->node23 + + - - -node22 - -sampling_decision.h + + +node64 + +propagation_style.h - + -node4->node22 - - +node4->node64 + + - - -node85 - -propagation_styles.h + + +node77 + +optional.h - - -node4->node85 - - + + +node4->node77 + + node5 - -dict_writer.h + +tag_propagation.cpp - - -node6 - -tag_propagation.cpp + + +node5->node38 + + - - -node6->node32 - - + + +node40 + +tag_propagation.h - - -node34 - -tag_propagation.h + + +node5->node40 + + - - -node6->node34 - - + + +node48 + +parse_util.h - - -node42 - -parse_util.h + + +node5->node48 + + - - -node6->node42 - - + + +node6 + +dict_writer.h - - -node8 - -span_sampler.h + + +node6->node8 + + - - -node14 - -limiter.h + + +node95 + +absl/strings/string_view.h - + -node8->node14 - - +node8->node95 + + - - -node8->node22 - - + + +node9 + +span_sampler.h - - -node30 - -json_fwd.hpp + + +node15 + +limiter.h - - -node8->node30 - - + + +node9->node15 + + - - -node36 - -clock.h + + +node9->node23 + + - - -node8->node36 - - + + +node35 + +json_fwd.hpp - - -node75 - -span_sampler_config.h + + +node9->node35 + + - - -node8->node75 - - + + +node41 + +clock.h - - -node9 - -dict_reader.cpp + + +node9->node41 + + - - -node77 - -dict_reader.h + + +node81 + +span_sampler_config.h - + -node9->node77 - - +node9->node81 + + node10 - -tracer_config.h + +dict_reader.cpp - - -node10->node13 - - - - - -node21 - -datadog_agent_config.h + + +node84 + +dict_reader.h - - -node10->node21 - - + + +node10->node84 + + - + -node10->node32 - - +node11->node8 + + - - -node10->node37 - - + + +node12 + +tracer_config.h - - -node10->node75 - - + + +node12->node14 + + - - -node10->node85 - - + + +node25 + +datadog_agent_config.h - - -node89 - -trace_sampler_config.h + + +node12->node25 + + - - -node10->node89 - - + + +node12->node38 + + - - -node12 - -curl/curl.h + + +node12->node43 + + - + + +node12->node64 + + + + -node13->node32 - - +node12->node81 + + + + + +node96 + +trace_sampler_config.h - + -node14->node18 - - +node12->node96 + + - - -node14->node36 - - + + +node13 + +curl/curl.h - - -node15 - -span.h + + +node14->node38 + + - + -node15->node32 - - +node14->node77 + + - - -node15->node36 - - - - - -node64 - -id_generator.h + + +node15->node20 + + - - -node15->node64 - - + + +node15->node41 + + node16 - -sampling_mechanism.cpp + +optional.cpp - - -node23 - -sampling_mechanism.h - - - -node16->node23 - - + + +node16->node77 + + node17 - -logger.cpp - - - -node17->node32 - - - - - -node35 - -logger.h - - - -node17->node35 - - + +span.h - - -node18->node13 - - + + +node17->node8 + + - - -node19 - -sampling_util.h + + +node17->node38 + + - + -node19->node18 - - +node17->node41 + + - - -node20->node13 - - + + +node72 + +id_generator.h - + -node20->node36 - - +node17->node72 + + - + -node21->node13 - - - - - -node81 - -http_client.h +node17->node77 + + - - -node21->node81 - - + + +node18 + +sampling_mechanism.cpp - - -node22->node18 - - + + +node26 + +sampling_mechanism.h - + -node22->node23 - - +node18->node26 + + - - -node24 - -msgpack.cpp + + +node19 + +logger.cpp + + + +node19->node38 + + - + + +node42 + +logger.h + + + +node19->node42 + + + + -node24->node32 - - +node20->node14 + + - - -node24->node55 - - + + +node21 + +sampling_util.h - - -node26 - -datadog_agent_config.cpp + + +node21->node20 + + - + + +node22 + +string_view.cpp + + -node26->node21 - - +node22->node8 + + + + + +node23->node20 + + - + -node26->node25 - - +node23->node26 + + - + -node26->node40 - - +node23->node77 + + - - -node26->node42 - - + + +node24->node8 + + - - -node60 - -environment.h + + +node24->node14 + + - - -node26->node60 - - + + +node24->node41 + + + + + +node24->node77 + + + + + +node25->node8 + + + + + +node25->node14 + + + + + +node88 + +http_client.h + + + +node25->node88 + + node27 - -sampling_util.cpp + +glob.h - - -node27->node19 - - + + +node27->node8 + + node28 - -event_scheduler.cpp + +msgpack.cpp - - -node33 - -event_scheduler.h + + +node28->node38 + + - - -node28->node33 - - + + +node28->node61 + + node29 - -span.cpp - - - -node29->node4 - - + +absl/types/optional.h - - -node29->node5 - - + + +node31 + +sampling_util.cpp - - -node29->node11 - - + + +node31->node21 + + - - -node29->node15 - - + + +node32 + +datadog_agent_config.cpp - - -node29->node20 - - + + +node32->node25 + + - - -node29->node61 - - + + +node32->node30 + + - - -node31 - -datadog_agent.h + + +node32->node46 + + - + -node31->node33 - - +node32->node48 + + - - -node31->node36 - - + + +node67 + +environment.h - - -node50 - -collector.h + + +node32->node67 + + - - -node31->node50 - - + + +node33 + +span.cpp - - -node31->node81 - - + + +node33->node4 + + - - -node33->node30 - - + + +node33->node6 + + - - -node33->node32 - - + + +node33->node8 + + - - -node34->node13 - - + + +node33->node11 + + - - -node37->node30 - - + + +node33->node17 + + - - -node38 - -curl.h + + +node33->node24 + + - + -node38->node30 - - +node33->node68 + + - - -node38->node81 - - + + +node33->node77 + + + + + +node34 + +event_scheduler.cpp node39 - -span_defaults.cpp - - - -node39->node7 - - - - - -node39->node37 - - + +event_scheduler.h - - -node40->node33 - - + + +node34->node39 + + - - -node41 - -tracer.h + + +node36 + +datadog_agent.h - - -node41->node10 - - + + +node36->node39 + + - + -node41->node13 - - - - - -node41->node15 - - - - - -node41->node32 - - +node36->node41 + + - - -node41->node36 - - + + +node56 + +collector.h - - -node41->node64 - - + + +node36->node56 + + - + -node42->node13 - - - - - -node43 - -expected.cpp +node36->node88 + + - - -node43->node13 - - + + +node37 + +propagation_style.cpp - - -node44 - -collector.cpp + + +node37->node7 + + - + -node44->node50 - - - - - -node45 - -id_generator.cpp - - - -node45->node64 - - +node37->node64 + + - - -node46 - -trace_sampler.cpp + + +node38->node8 + + - - -node46->node7 - - + + +node39->node35 + + - - -node46->node19 - - + + +node39->node38 + + - + -node46->node20 - - +node40->node8 + + + + + +node40->node14 + + - + -node46->node22 - - +node42->node8 + + - - -node52 - -collector_response.h + + +node43->node35 + + - - -node46->node52 - - + + +node44 + +curl.h - - -node56 - -trace_sampler.h + + +node44->node35 + + - - -node46->node56 - - + + +node44->node88 + + - - -node84 - -sampling_priority.h + + +node45 + +span_defaults.cpp - - -node46->node84 - - + + +node45->node7 + + + + + +node45->node43 + + + + + +node46->node39 + + node47 - -sampling_decision.cpp + +tracer.h - - -node47->node22 - - + + +node47->node12 + + - - -node48 - -sampling_priority.cpp + + +node47->node14 + + - - -node48->node84 - - + + +node47->node17 + + - - -node49 - -span_sampler.cpp + + +node47->node38 + + - + -node49->node7 - - +node47->node41 + + - + -node49->node8 - - +node47->node72 + + - - -node49->node19 - - + + +node47->node77 + + - - -node49->node20 - - + + +node48->node8 + + - - -node49->node23 - - + + +node48->node14 + + - - -node49->node84 - - + + +node49 + +expected.cpp - - -node50->node13 - - + + +node49->node14 + + - - -node50->node30 - - + + +node50 + +collector.cpp + + + +node50->node56 + + node51 - -curl.cpp + +id_generator.cpp - - -node51->node5 - - + + +node51->node72 + + - - -node51->node7 - - + + +node52 + +trace_sampler.cpp - - -node51->node12 - - + + +node52->node7 + + - - -node51->node35 - - + + +node52->node21 + + - - -node51->node38 - - + + +node52->node23 + + - - -node51->node42 - - + + +node52->node24 + + - - -node51->node77 - - + + +node60 + +collector_response.h - - -node51->node81 - - + + +node52->node60 + + + + + +node62 + +trace_sampler.h - + -node52->node18 - - +node52->node62 + + + + + +node91 + +sampling_priority.h + + + +node52->node91 + + node53 - -cerr_logger.cpp - - - -node90 - -cerr_logger.h + +sampling_decision.cpp - - -node53->node90 - - + + +node53->node23 + + node54 - -null_collector.cpp - - - -node54->node7 - - - - - -node71 - -null_collector.h + +sampling_priority.cpp - - -node54->node71 - - + + +node54->node91 + + - - -node55->node13 - - + + +node55 + +span_sampler.cpp - - -node56->node14 - - + + +node55->node7 + + - - -node56->node18 - - + + +node55->node9 + + - + -node56->node30 - - - - - -node56->node36 - - +node55->node21 + + - - -node56->node89 - - + + +node55->node24 + + - - -node57 - -span_config.cpp + + +node55->node26 + + - + -node57->node61 - - - - - -node58 - -dict_writer.cpp - - - -node58->node5 - - - - - -node59 - -trace_sampler_config.cpp +node55->node91 + + - + -node59->node7 - - - - - -node59->node42 - - - - - -node59->node60 - - - - - -node59->node89 - - +node56->node14 + + - + -node60->node30 - - - - - -node61->node36 - - +node56->node35 + + - - -node62 - -datadog_agent.cpp + + +node56->node77 + + - - -node62->node5 - - + + +node57 + +curl.cpp - + -node62->node7 - - +node57->node6 + + - - -node62->node20 - - + + +node57->node7 + + - + -node62->node21 - - +node57->node8 + + - + -node62->node31 - - +node57->node13 + + - - -node62->node35 - - + + +node57->node42 + + - + -node62->node52 - - +node57->node44 + + - - -node62->node55 - - + + +node57->node48 + + + + + +node57->node84 + + - + -node62->node56 - - +node57->node88 + + - - -node72 - -version.h + + +node58 + +null_collector.cpp - - -node62->node72 - - + + +node58->node7 + + - - -node63 - -winsock.h + + +node78 + +null_collector.h - - -node65 - -environment.cpp + + +node58->node78 + + + + + +node59 + +cerr_logger.cpp + + + +node98 + +cerr_logger.h - + -node65->node7 - - +node59->node98 + + - - -node65->node60 - - + + +node60->node8 + + - - -node66 - -tracer_config.cpp + + +node60->node20 + + - + -node66->node10 - - - - - -node66->node31 - - +node61->node8 + + - - -node66->node42 - - + + +node61->node14 + + - - -node66->node60 - - + + +node62->node15 + + - - -node66->node71 - - + + +node62->node20 + + - - -node66->node90 - - + + +node62->node35 + + - - -node67 - -net_util.cpp + + +node62->node41 + + - + -node67->node63 - - +node62->node77 + + - - -node87 - -net_util.h + + +node62->node96 + + - - -node67->node87 - - + + +node63 + +span_config.cpp - - -node68 - -parse_util.cpp + + +node63->node68 + + - + -node68->node32 - - - - - -node68->node42 - - +node64->node35 + + - - -node70 - -charconv + + +node65 + +dict_writer.cpp - - -node68->node70 - - + + +node65->node6 + + - - -node69 - -http_client.cpp + + +node66 + +trace_sampler_config.cpp - - -node69->node81 - - + + +node66->node7 + + - + -node71->node50 - - +node66->node48 + + - - -node73 - -version.cpp + + +node66->node67 + + - + -node73->node72 - - - - - -node74 - -span_matcher.h +node66->node96 + + - - -node74->node13 - - - - - -node74->node30 - - - - + -node75->node13 - - +node67->node8 + + - + + +node67->node35 + + + + -node75->node18 - - +node67->node77 + + - + -node75->node30 - - +node68->node41 + + - - -node75->node74 - - + + +node68->node77 + + - - -node76 - -propagation_styles.cpp + + +node69 + +datadog_agent.cpp - - -node76->node7 - - + + +node69->node6 + + - - -node76->node85 - - + + +node69->node7 + + - - -node78 - -span_matcher.cpp + + +node69->node24 + + - + -node78->node7 - - - - - -node78->node20 - - +node69->node25 + + - - -node78->node32 - - + + +node69->node36 + + - - -node78->node74 - - + + +node69->node42 + + - - -node79 - -default_http_client_curl.cpp + + +node69->node60 + + - - -node79->node25 - - + + +node69->node61 + + - + -node79->node38 - - +node69->node62 + + node80 - -tracer.cpp + +version.h - - -node80->node4 - - + + +node69->node80 + + - - -node80->node7 - - + + +node70 + +winsock.h - + + +node71 + +environment.cpp + + -node80->node8 - - +node71->node7 + + - - -node80->node11 - - + + +node71->node67 + + - - -node80->node15 - - + + +node73 + +tracer_config.cpp - - -node80->node20 - - + + +node73->node7 + + - - -node80->node31 - - + + +node73->node8 + + - - -node80->node34 - - + + +node73->node12 + + - - -node80->node35 - - + + +node73->node36 + + - - -node80->node41 - - + + +node73->node48 + + - + -node80->node42 - - +node73->node67 + + - - -node80->node56 - - + + +node73->node78 + + - - -node80->node60 - - + + +node73->node98 + + - - -node80->node61 - - + + +node74 + +net_util.cpp - - -node80->node72 - - + + +node74->node70 + + + + + +node92 + +net_util.h - + -node80->node77 - - +node74->node92 + + - - -node80->node87 - - + + +node75 + +parse_util.cpp - + -node81->node13 - - +node75->node38 + + + + + +node75->node48 + + + + + +node79 + +charconv - + + +node75->node79 + + + + + +node76 + +http_client.cpp + + -node81->node30 - - +node76->node88 + + - + -node81->node32 - - - - - -node82 - -clock.cpp +node77->node29 + + - + -node82->node36 - - - - - -node83 - -collector_response.cpp +node78->node56 + + - + -node83->node52 - - +node80->node8 + + - + -node84->node23 - - +node81->node14 + + - + -node85->node30 - - +node81->node20 + + - - -node86 - -limiter.cpp - - - -node86->node14 - - - - - -node88 - -error.cpp + + +node81->node35 + + - + -node88->node32 - - +node81->node77 + + - - -node89->node13 - - + + +node82 + +span_matcher.h - - -node89->node18 - - + + +node81->node82 + + - - -node89->node30 - - + + +node82->node14 + + - + -node89->node74 - - +node82->node35 + + - - -node90->node35 - - + + +node83 + +version.cpp - - -node91 - -tags.cpp + + +node83->node80 + + - - -node91->node11 - - + + +node84->node8 + + - + -node91->node42 - - - - - -node92 - -trace_segment.cpp +node84->node77 + + - - -node92->node4 - - + + +node85 + +span_matcher.cpp - - -node92->node5 - - + + +node85->node7 + + - - -node92->node8 - - + + +node85->node24 + + - - -node92->node11 - - + + +node85->node38 + + - + -node92->node20 - - +node85->node77 + + - - -node92->node32 - - + + +node85->node82 + + + + + +node86 + +tracer.cpp - + -node92->node34 - - +node86->node4 + + - - -node92->node35 - - + + +node86->node7 + + - - -node92->node50 - - + + +node86->node9 + + - - -node92->node52 - - + + +node86->node11 + + + + + +node86->node17 + + + + + +node86->node24 + + - + -node92->node56 - - +node86->node36 + + - - -node92->node70 - - + + +node86->node40 + + - - -node93 - -span_sampler_config.cpp + + +node86->node42 + + - - -node93->node7 - - + + +node86->node47 + + - - -node93->node13 - - + + +node86->node48 + + - + -node93->node35 - - +node86->node62 + + - - -node93->node60 - - + + +node86->node67 + + - - -node93->node75 - - + + +node86->node68 + + + + + +node86->node80 + + + + + +node86->node84 + + + + + +node86->node92 + + + + + +node87 + +default_http_client_curl.cpp + + + +node87->node30 + + + + + +node87->node44 + + + + + +node88->node14 + + + + + +node88->node35 + + + + + +node88->node38 + + + + + +node88->node77 + + + + + +node89 + +clock.cpp + + + +node89->node41 + + + + + +node90 + +collector_response.cpp + + + +node90->node60 + + + + + +node91->node26 + + + + + +node92->node77 + + + + + +node93 + +limiter.cpp + + + +node93->node15 + + + + + +node94 + +error.cpp + + + +node94->node38 + + + + + +node96->node14 + + + + + +node96->node20 + + + + + +node96->node35 + + + + + +node96->node77 + + + + + +node96->node82 + + + + + +node97 + +tags.cpp + + + +node97->node11 + + + + + +node97->node48 + + + + + +node98->node42 + + + + + +node99 + +trace_segment.cpp + + + +node99->node4 + + + + + +node99->node6 + + + + + +node99->node9 + + + + + +node99->node11 + + + + + +node99->node24 + + + + + +node99->node38 + + + + + +node99->node40 + + + + + +node99->node42 + + + + + +node99->node56 + + + + + +node99->node60 + + + + + +node99->node62 + + + + + +node99->node77 + + + + + +node99->node79 + + + + + +node100 + +span_sampler_config.cpp + + + +node100->node7 + + + + + +node100->node14 + + + + + +node100->node42 + + + + + +node100->node67 + + + + + +node100->node81 + + diff --git a/src/datadog/environment.h b/src/datadog/environment.h index 9e878af9..fbcd78c3 100644 --- a/src/datadog/environment.h +++ b/src/datadog/environment.h @@ -29,6 +29,9 @@ namespace environment { MACRO(DD_ENV) \ MACRO(DD_PROPAGATION_STYLE_EXTRACT) \ MACRO(DD_PROPAGATION_STYLE_INJECT) \ + MACRO(DD_TRACE_PROPAGATION_STYLE_EXTRACT) \ + MACRO(DD_TRACE_PROPAGATION_STYLE_INJECT) \ + MACRO(DD_TRACE_PROPAGATION_STYLE) \ MACRO(DD_SERVICE) \ MACRO(DD_SPAN_SAMPLING_RULES) \ MACRO(DD_SPAN_SAMPLING_RULES_FILE) \ diff --git a/src/datadog/error.h b/src/datadog/error.h index f19eae01..97799604 100644 --- a/src/datadog/error.h +++ b/src/datadog/error.h @@ -67,6 +67,8 @@ struct Error { INVALID_DOUBLE = 42, MISSING_TRACE_ID = 43, ENVOY_HTTP_CLIENT_FAILURE = 44, + MULTIPLE_PROPAGATION_STYLE_ENVIRONMENT_VARIABLES = 45, + DUPLICATE_PROPAGATION_STYLE = 46, }; Code code; diff --git a/src/datadog/optional.h b/src/datadog/optional.h index 8ce7be2b..ae1deb7c 100644 --- a/src/datadog/optional.h +++ b/src/datadog/optional.h @@ -33,6 +33,8 @@ #include #endif // defined DD_USE_ABSEIL_FOR_ENVOY +#include // std::forward + namespace datadog { namespace tracing { @@ -46,5 +48,17 @@ using Optional = std::optional; inline constexpr auto nullopt = std::nullopt; #endif // defined DD_USE_ABSEIL_FOR_ENVOY +// Return the first non-null argument value. The last argument must not be +// `Optional`. +template +auto value_or(Value&& value) { + return std::forward(value); +} + +template +auto value_or(Optional maybe, Rest&&... rest) { + return maybe.value_or(value_or(std::forward(rest)...)); +} + } // namespace tracing } // namespace datadog diff --git a/src/datadog/propagation_style.cpp b/src/datadog/propagation_style.cpp new file mode 100644 index 00000000..146c6cd1 --- /dev/null +++ b/src/datadog/propagation_style.cpp @@ -0,0 +1,31 @@ +#include "propagation_style.h" + +#include + +#include "json.hpp" + +namespace datadog { +namespace tracing { + +nlohmann::json to_json(PropagationStyle style) { + switch (style) { + case PropagationStyle::DATADOG: + return "datadog"; + case PropagationStyle::B3: + return "B3"; + default: + assert(style == PropagationStyle::NONE); + return "none"; + } +} + +nlohmann::json to_json(const std::vector& styles) { + std::vector styles_json; + for (const auto style : styles) { + styles_json.push_back(to_json(style)); + } + return styles_json; +} + +} // namespace tracing +} // namespace datadog diff --git a/src/datadog/propagation_style.h b/src/datadog/propagation_style.h new file mode 100644 index 00000000..66d29786 --- /dev/null +++ b/src/datadog/propagation_style.h @@ -0,0 +1,30 @@ +#pragma once + +// This component provides an `enum class`, `PropagationStyle`, that indicates a +// trace context extraction or injection format to be used. `TracerConfig` has +// one `std::vector` for extraction and another for injection. +// See `tracer_config.h`. + +#include + +#include "json_fwd.hpp" + +namespace datadog { +namespace tracing { + +enum class PropagationStyle { + // Datadog headers, e.g. X-Datadog-Trace-ID + DATADOG, + // B3 multi-header style, e.g. X-B3-TraceID + B3, + // The absence of propagation. If this is the only style set, then + // propagation is disabled in the relevant direction (extraction or + // injection). + NONE, +}; + +nlohmann::json to_json(PropagationStyle style); +nlohmann::json to_json(const std::vector& styles); + +} // namespace tracing +} // namespace datadog diff --git a/src/datadog/propagation_styles.cpp b/src/datadog/propagation_styles.cpp deleted file mode 100644 index 55ce6b50..00000000 --- a/src/datadog/propagation_styles.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "propagation_styles.h" - -#include -#include - -#include "json.hpp" - -namespace datadog { -namespace tracing { - -nlohmann::json to_json(const PropagationStyles& styles) { - std::vector selected_names; - if (styles.datadog) { - selected_names.emplace_back("datadog"); - } - if (styles.b3) { - selected_names.emplace_back("B3"); - } - return selected_names; -} - -} // namespace tracing -} // namespace datadog diff --git a/src/datadog/propagation_styles.h b/src/datadog/propagation_styles.h deleted file mode 100644 index ce0e4fb1..00000000 --- a/src/datadog/propagation_styles.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -// This component provides a `struct`, `PropagationStyles`, that specifies which -// trace context extraction or injection formats are to be used. `TracerConfig` -// has one `PropagationStyles` for extraction and another for injection. See -// `tracer_config.h`. - -#include "json_fwd.hpp" - -namespace datadog { -namespace tracing { - -struct PropagationStyles { - bool datadog = true; - bool b3 = false; -}; - -nlohmann::json to_json(const PropagationStyles&); - -} // namespace tracing -} // namespace datadog diff --git a/src/datadog/trace_segment.cpp b/src/datadog/trace_segment.cpp index 9253ae19..ac70d96e 100644 --- a/src/datadog/trace_segment.cpp +++ b/src/datadog/trace_segment.cpp @@ -45,7 +45,7 @@ TraceSegment::TraceSegment( const std::shared_ptr& trace_sampler, const std::shared_ptr& span_sampler, const std::shared_ptr& defaults, - const PropagationStyles& injection_styles, + const std::vector& injection_styles, const Optional& hostname, Optional origin, std::size_t tags_header_max_size, std::unordered_map trace_tags, @@ -221,8 +221,14 @@ void TraceSegment::inject(DictWriter& writer, const SpanData& span) { encoded_trace_tags = encode_tags(trace_tags_); } - // Origin and trace tag headers are always propagated. + // Origin and trace tag headers are always propagated, unless the only + // injection style is "none". // Other headers depend on the injection styles. + if (injection_styles_.size() == 1 && + injection_styles_[0] == PropagationStyle::NONE) { + return; + } + if (origin_) { writer.set("x-datadog-origin", *origin_); } @@ -242,17 +248,22 @@ void TraceSegment::inject(DictWriter& writer, const SpanData& span) { writer.set("x-datadog-tags", encoded_trace_tags); } - if (injection_styles_.datadog) { - writer.set("x-datadog-trace-id", std::to_string(span.trace_id)); - writer.set("x-datadog-parent-id", std::to_string(span.span_id)); - writer.set("x-datadog-sampling-priority", - std::to_string(sampling_priority)); - } - - if (injection_styles_.b3) { - writer.set("x-b3-traceid", hex(span.trace_id)); - writer.set("x-b3-spanid", hex(span.span_id)); - writer.set("x-b3-sampled", std::to_string(int(sampling_priority > 0))); + for (const auto style : injection_styles_) { + switch (style) { + case PropagationStyle::DATADOG: + writer.set("x-datadog-trace-id", std::to_string(span.trace_id)); + writer.set("x-datadog-parent-id", std::to_string(span.span_id)); + writer.set("x-datadog-sampling-priority", + std::to_string(sampling_priority)); + break; + case PropagationStyle::B3: + writer.set("x-b3-traceid", hex(span.trace_id)); + writer.set("x-b3-spanid", hex(span.span_id)); + writer.set("x-b3-sampled", std::to_string(int(sampling_priority > 0))); + break; + case PropagationStyle::NONE: + break; + } } } diff --git a/src/datadog/trace_segment.h b/src/datadog/trace_segment.h index 2e095b18..0256e405 100644 --- a/src/datadog/trace_segment.h +++ b/src/datadog/trace_segment.h @@ -34,7 +34,7 @@ #include "expected.h" #include "optional.h" -#include "propagation_styles.h" +#include "propagation_style.h" #include "sampling_decision.h" namespace datadog { @@ -58,7 +58,7 @@ class TraceSegment { std::shared_ptr span_sampler_; std::shared_ptr defaults_; - const PropagationStyles injection_styles_; + const std::vector injection_styles_; const Optional hostname_; const Optional origin_; const std::size_t tags_header_max_size_; @@ -75,7 +75,7 @@ class TraceSegment { const std::shared_ptr& trace_sampler, const std::shared_ptr& span_sampler, const std::shared_ptr& defaults, - const PropagationStyles& injection_styles, + const std::vector& injection_styles, const Optional& hostname, Optional origin, std::size_t tags_header_max_size, std::unordered_map trace_tags, diff --git a/src/datadog/tracer.cpp b/src/datadog/tracer.cpp index 79f43672..81f3bf25 100644 --- a/src/datadog/tracer.cpp +++ b/src/datadog/tracer.cpp @@ -24,186 +24,128 @@ namespace datadog { namespace tracing { namespace { -class ExtractionPolicy { - public: - virtual Expected> trace_id( - const DictReader& headers) = 0; - virtual Expected> parent_id( - const DictReader& headers) = 0; - virtual Expected> sampling_priority( - const DictReader& headers) = 0; - virtual Optional origin(const DictReader& headers) = 0; - virtual Optional trace_tags(const DictReader&) = 0; +Expected> extract_id_header(const DictReader& headers, + StringView header, + StringView header_kind, + StringView style_name, + int base) { + auto found = headers.lookup(header); + if (!found) { + return nullopt; + } + auto result = parse_uint64(*found, base); + if (auto* error = result.if_error()) { + std::string prefix; + prefix += "Could not extract "; + append(prefix, style_name); + prefix += "-style "; + append(prefix, header_kind); + prefix += "ID from "; + append(prefix, header); + prefix += ": "; + append(prefix, *found); + prefix += ' '; + return error->with_prefix(prefix); + } + return *result; +} + +struct ExtractedData { + Optional trace_id; + Optional parent_id; + Optional origin; + Optional trace_tags; + Optional sampling_priority; }; -class DatadogExtractionPolicy : public ExtractionPolicy { - Expected> id(const DictReader& headers, - StringView header, StringView kind) { - auto found = headers.lookup(header); - if (!found) { - return nullopt; - } - auto result = parse_uint64(*found, 10); - if (auto* error = result.if_error()) { - std::string prefix; - prefix += "Could not extract Datadog-style "; - append(prefix, kind); - prefix += "ID from "; - append(prefix, header); - prefix += ": "; - append(prefix, *found); - prefix += ' '; - return error->with_prefix(prefix); - } - return *result; - } +Expected extract_datadog(const DictReader& headers) { + ExtractedData result; - public: - Expected> trace_id( - const DictReader& headers) override { - return id(headers, "x-datadog-trace-id", "trace"); + auto trace_id = + extract_id_header(headers, "x-datadog-trace-id", "trace", "Datadog", 10); + if (auto* error = trace_id.if_error()) { + return std::move(*error); } + result.trace_id = *trace_id; - Expected> parent_id( - const DictReader& headers) override { - return id(headers, "x-datadog-parent-id", "parent span"); + auto parent_id = extract_id_header(headers, "x-datadog-parent-id", + "parent span", "Datadog", 10); + if (auto* error = parent_id.if_error()) { + return std::move(*error); } + result.parent_id = *parent_id; - Expected> sampling_priority( - const DictReader& headers) override { - const StringView header = "x-datadog-sampling-priority"; - auto found = headers.lookup(header); - if (!found) { - return nullopt; - } - auto result = parse_int(*found, 10); - if (auto* error = result.if_error()) { + const StringView sampling_priority_header = "x-datadog-sampling-priority"; + if (auto found = headers.lookup(sampling_priority_header)) { + auto sampling_priority = parse_int(*found, 10); + if (auto* error = sampling_priority.if_error()) { std::string prefix; prefix += "Could not extract Datadog-style sampling priority from "; - append(prefix, header); + append(prefix, sampling_priority_header); prefix += ": "; append(prefix, *found); prefix += ' '; return error->with_prefix(prefix); } - return *result; + result.sampling_priority = *sampling_priority; } - Optional origin(const DictReader& headers) override { - auto found = headers.lookup("x-datadog-origin"); - if (found) { - return std::string(*found); - } - return nullopt; + auto origin = headers.lookup("x-datadog-origin"); + if (origin) { + result.origin = std::string(*origin); } - Optional trace_tags(const DictReader& headers) override { - auto found = headers.lookup("x-datadog-tags"); - if (found) { - return std::string(*found); - } - return nullopt; + auto trace_tags = headers.lookup("x-datadog-tags"); + if (trace_tags) { + result.trace_tags = std::string(*trace_tags); } -}; -class B3ExtractionPolicy : public DatadogExtractionPolicy { - Expected> id(const DictReader& headers, - StringView header, StringView kind) { - auto found = headers.lookup(header); - if (!found) { - return nullopt; - } - auto result = parse_uint64(*found, 16); - if (auto* error = result.if_error()) { - std::string prefix; - prefix += "Could not extract B3-style "; - append(prefix, kind); - prefix += "ID from "; - append(prefix, header); - prefix += ": "; - append(prefix, *found); - prefix += ' '; - return error->with_prefix(prefix); - } - return *result; - } + return result; +} - public: - Expected> trace_id( - const DictReader& headers) override { - return id(headers, "x-b3-traceid", "trace"); +Expected extract_b3(const DictReader& headers) { + ExtractedData result; + + auto trace_id = extract_id_header(headers, "x-b3-traceid", "trace", "B3", 16); + if (auto* error = trace_id.if_error()) { + return std::move(*error); } + result.trace_id = *trace_id; - Expected> parent_id( - const DictReader& headers) override { - return id(headers, "x-b3-spanid", "parent span"); + auto parent_id = + extract_id_header(headers, "x-b3-spanid", "parent span", "B3", 16); + if (auto* error = parent_id.if_error()) { + return std::move(*error); } + result.parent_id = *parent_id; - Expected> sampling_priority( - const DictReader& headers) override { - const StringView header = "x-b3-sampled"; - auto found = headers.lookup(header); - if (!found) { - return nullopt; - } - auto result = parse_int(*found, 10); - if (auto* error = result.if_error()) { + const StringView sampling_priority_header = "x-b3-sampled"; + if (auto found = headers.lookup(sampling_priority_header)) { + auto sampling_priority = parse_int(*found, 10); + if (auto* error = sampling_priority.if_error()) { std::string prefix; prefix += "Could not extract B3-style sampling priority from "; - append(prefix, header); + append(prefix, sampling_priority_header); prefix += ": "; append(prefix, *found); prefix += ' '; return error->with_prefix(prefix); } - return *result; + result.sampling_priority = *sampling_priority; } -}; -struct ExtractedData { - Optional trace_id; - Optional parent_id; - Optional origin; - Optional trace_tags; - Optional sampling_priority; -}; - -bool operator!=(const ExtractedData& left, const ExtractedData& right) { - return left.trace_id != right.trace_id || left.parent_id != right.parent_id || - left.origin != right.origin || left.trace_tags != right.trace_tags || - left.sampling_priority != right.sampling_priority; -} - -Expected extract_data(ExtractionPolicy& extract, - const DictReader& reader) { - ExtractedData extracted_data; - - auto& [trace_id, parent_id, origin, trace_tags, sampling_priority] = - extracted_data; - - auto maybe_trace_id = extract.trace_id(reader); - if (auto* error = maybe_trace_id.if_error()) { - return std::move(*error); + // Origin and trace tags are still extracted, but from the Datadog headers. + auto origin = headers.lookup("x-datadog-origin"); + if (origin) { + result.origin = std::string(*origin); } - trace_id = *maybe_trace_id; - - origin = extract.origin(reader); - auto maybe_parent_id = extract.parent_id(reader); - if (auto* error = maybe_parent_id.if_error()) { - return std::move(*error); - } - parent_id = *maybe_parent_id; - - auto maybe_sampling_priority = extract.sampling_priority(reader); - if (auto* error = maybe_sampling_priority.if_error()) { - return std::move(*error); + auto trace_tags = headers.lookup("x-datadog-tags"); + if (trace_tags) { + result.trace_tags = std::string(*trace_tags); } - sampling_priority = *maybe_sampling_priority; - - trace_tags = extract.trace_tags(reader); - return extracted_data; + return result; } void log_startup_message(Logger& logger, StringView tracer_version_string, @@ -211,8 +153,8 @@ void log_startup_message(Logger& logger, StringView tracer_version_string, const SpanDefaults& defaults, const TraceSampler& trace_sampler, const SpanSampler& span_sampler, - const PropagationStyles& injection_styles, - const PropagationStyles& extraction_styles, + const std::vector& injection_styles, + const std::vector& extraction_styles, const Optional& hostname, std::size_t tags_header_max_size) { // clang-format off @@ -300,41 +242,40 @@ Expected Tracer::extract_span(const DictReader& reader) { Expected Tracer::extract_span(const DictReader& reader, const SpanConfig& config) { - assert(extraction_styles_.datadog || extraction_styles_.b3); + assert(!extraction_styles_.empty()); - Optional extracted_data; - const char* extracted_by; + ExtractedData extracted_data; - if (extraction_styles_.datadog) { - DatadogExtractionPolicy extract; - auto data = extract_data(extract, reader); - if (auto* error = data.if_error()) { - return std::move(*error); + for (const auto style : extraction_styles_) { + using Extractor = decltype(&extract_datadog); // function pointer + Extractor extract; + switch (style) { + case PropagationStyle::DATADOG: + extract = &extract_datadog; + break; + case PropagationStyle::B3: + extract = &extract_b3; + break; + default: + assert(style == PropagationStyle::NONE); + extracted_data = ExtractedData{}; + continue; } - extracted_data = *data; - extracted_by = "Datadog"; - } - - if (extraction_styles_.b3) { - B3ExtractionPolicy extract; - auto data = extract_data(extract, reader); + auto data = extract(reader); if (auto* error = data.if_error()) { return std::move(*error); } - if (extracted_data && *data != *extracted_data) { - std::string message; - message += "B3 extracted different data than did "; - message += extracted_by; - // TODO: diagnose difference - return Error{Error::INCONSISTENT_EXTRACTION_STYLES, std::move(message)}; - } extracted_data = *data; - extracted_by = "B3"; + // If the extractor produced a non-null trace ID, then we consider this + // extraction style the one "chosen" for this trace. + // Otherwise, we loop around to the next configured extraction style. + if (extracted_data.trace_id) { + break; + } } - assert(extracted_data); auto& [trace_id, parent_id, origin, trace_tags, sampling_priority] = - *extracted_data; + extracted_data; // Some information might be missing. // Here are the combinations considered: @@ -349,7 +290,6 @@ Expected Tracer::extract_span(const DictReader& reader, // producing a root span // - if origin is _not_ set, then it's an error // - trace ID and parent ID means we're extracting a child span - // - parent ID without trace ID is an error if (!trace_id && !parent_id) { return Error{Error::NO_SPAN_TO_EXTRACT, diff --git a/src/datadog/tracer.h b/src/datadog/tracer.h index d3a6f0ae..b894c791 100644 --- a/src/datadog/tracer.h +++ b/src/datadog/tracer.h @@ -34,8 +34,8 @@ class Tracer { IDGenerator generator_; Clock clock_; std::shared_ptr defaults_; - PropagationStyles injection_styles_; - PropagationStyles extraction_styles_; + std::vector injection_styles_; + std::vector extraction_styles_; Optional hostname_; std::size_t tags_header_max_size_; diff --git a/src/datadog/tracer_config.cpp b/src/datadog/tracer_config.cpp index 32656166..814bbef3 100644 --- a/src/datadog/tracer_config.cpp +++ b/src/datadog/tracer_config.cpp @@ -1,6 +1,7 @@ #include "tracer_config.h" #include +#include #include #include #include @@ -10,6 +11,7 @@ #include "cerr_logger.h" #include "datadog_agent.h" #include "environment.h" +#include "json.hpp" #include "null_collector.h" #include "parse_util.h" #include "string_view.h" @@ -67,17 +69,37 @@ std::vector parse_list(StringView input) { return items; } -Expected parse_propagation_styles(StringView input) { - PropagationStyles styles{false, false}; +Expected> parse_propagation_styles( + StringView input) { + std::vector styles; + + const auto last_is_duplicate = [&]() -> Optional { + assert(!styles.empty()); + + const auto dupe = + std::find(styles.begin(), styles.end() - 1, styles.back()); + if (dupe == styles.end() - 1) { + return nullopt; // no duplicate + } + + std::string message; + message += "The propagation style "; + message += to_json(styles.back()).dump(); + message += " is duplicated in: "; + append(message, input); + return Error{Error::DUPLICATE_PROPAGATION_STYLE, std::move(message)}; + }; // Style names are separated by spaces, or a comma, or some combination. for (const StringView &item : parse_list(input)) { auto token = std::string(item); to_lower(token); if (token == "datadog") { - styles.datadog = true; - } else if (token == "b3") { - styles.b3 = true; + styles.push_back(PropagationStyle::DATADOG); + } else if (token == "b3" || token == "b3multi") { + styles.push_back(PropagationStyle::B3); + } else if (token == "none") { + styles.push_back(PropagationStyle::NONE); } else { std::string message; message += "Unsupported propagation style \""; @@ -87,6 +109,10 @@ Expected parse_propagation_styles(StringView input) { message += "\". The following styles are supported: Datadog, B3."; return Error{Error::UNKNOWN_PROPAGATION_STYLE, std::move(message)}; } + + if (auto maybe_error = last_is_duplicate()) { + return *maybe_error; + } } return styles; @@ -119,6 +145,133 @@ Expected> parse_tags( return tags; } +// Return a `std::vector` parsed from the specified `env_var`. +// If `env_var` is not in the environment, return `nullopt`. If an error occurs, +// throw an `Error`. +Optional> styles_from_env( + environment::Variable env_var) { + const auto styles_env = lookup(env_var); + if (!styles_env) { + return {}; + } + + auto styles = parse_propagation_styles(*styles_env); + if (auto *error = styles.if_error()) { + std::string prefix; + prefix += "Unable to parse "; + append(prefix, name(env_var)); + prefix += " environment variable: "; + throw error->with_prefix(prefix); + } + return *styles; +} + +std::string json_quoted(StringView text) { + std::string unquoted; + assign(unquoted, text); + return nlohmann::json(std::move(unquoted)).dump(); +} + +Expected finalize_propagation_styles(FinalizedTracerConfig &result, + const TracerConfig &config, + Logger &logger) { + namespace env = environment; + // Print a warning if a questionable combination of environment variables is + // defined. + const auto ts = env::DD_TRACE_PROPAGATION_STYLE; + const auto tse = env::DD_TRACE_PROPAGATION_STYLE_EXTRACT; + const auto se = env::DD_PROPAGATION_STYLE_EXTRACT; + const auto tsi = env::DD_TRACE_PROPAGATION_STYLE_INJECT; + const auto si = env::DD_PROPAGATION_STYLE_INJECT; + // clang-format off + /* + ts tse se tsi si + --- --- --- --- --- + ts | x warn warn warn warn + | + tse | x x warn ok ok + | + se | x x x ok ok + | + tsi | x x x x warn + | + si | x x x x x + */ + // In each pair, the first would be overridden by the second. + const std::pair questionable_combinations[] = { + {ts, tse}, {ts, se}, {ts, tsi}, {ts, si}, + + {se, tse}, /* ok */ /* ok */ + + /* ok */ /* ok */ + + {si, tsi}, + }; + // clang-format on + + const auto warn_message = [](StringView name, StringView value, + StringView name_override, + StringView value_override) { + std::string message; + message += "Both the environment variables "; + append(message, name); + message += "="; + message += json_quoted(value); + message += " and "; + append(message, name_override); + message += "="; + message += json_quoted(value_override); + message += " are defined. "; + append(message, name_override); + message += " will take precedence."; + return message; + }; + + for (const auto &[var, var_override] : questionable_combinations) { + const auto value = lookup(var); + if (!value) { + continue; + } + const auto value_override = lookup(var_override); + if (!value_override) { + continue; + } + const auto var_name = name(var); + const auto var_name_override = name(var_override); + logger.log_error(Error{ + Error::MULTIPLE_PROPAGATION_STYLE_ENVIRONMENT_VARIABLES, + warn_message(var_name, *value, var_name_override, *value_override)}); + } + + // Parse the propagation styles from the configuration and/or from the + // environment. + // Exceptions make this section simpler. + try { + const auto global_styles = styles_from_env(env::DD_TRACE_PROPAGATION_STYLE); + result.extraction_styles = + value_or(styles_from_env(env::DD_TRACE_PROPAGATION_STYLE_EXTRACT), + styles_from_env(env::DD_PROPAGATION_STYLE_EXTRACT), + global_styles, config.extraction_styles); + result.injection_styles = + value_or(styles_from_env(env::DD_TRACE_PROPAGATION_STYLE_INJECT), + styles_from_env(env::DD_PROPAGATION_STYLE_INJECT), + global_styles, config.injection_styles); + } catch (Error &error) { + return std::move(error); + } + + if (result.extraction_styles.empty()) { + return Error{Error::MISSING_SPAN_EXTRACTION_STYLE, + "At least one extraction style must be specified."}; + } + if (result.injection_styles.empty()) { + return Error{Error::MISSING_SPAN_INJECTION_STYLE, + "At least one injection style must be specified."}; + } + + return {}; +} + } // namespace Expected finalize_config(const TracerConfig &config) { @@ -193,38 +346,10 @@ Expected finalize_config(const TracerConfig &config) { return std::move(span_sampler_config.error()); } - result.extraction_styles = config.extraction_styles; - if (auto styles_env = lookup(environment::DD_PROPAGATION_STYLE_EXTRACT)) { - auto styles = parse_propagation_styles(*styles_env); - if (auto *error = styles.if_error()) { - std::string prefix; - prefix += "Unable to parse "; - append(prefix, name(environment::DD_PROPAGATION_STYLE_EXTRACT)); - prefix += " environment variable: "; - return error->with_prefix(prefix); - } - result.extraction_styles = *styles; - } - - result.injection_styles = config.injection_styles; - if (auto styles_env = lookup(environment::DD_PROPAGATION_STYLE_INJECT)) { - auto styles = parse_propagation_styles(*styles_env); - if (auto *error = styles.if_error()) { - std::string prefix; - prefix += "Unable to parse "; - append(prefix, name(environment::DD_PROPAGATION_STYLE_INJECT)); - prefix += " environment variable: "; - return error->with_prefix(prefix); - } - result.injection_styles = *styles; - } - - if (!result.extraction_styles.datadog && !result.extraction_styles.b3) { - return Error{Error::MISSING_SPAN_EXTRACTION_STYLE, - "At least one extraction style must be specified."}; - } else if (!result.injection_styles.datadog && !result.injection_styles.b3) { - return Error{Error::MISSING_SPAN_INJECTION_STYLE, - "At least one injection style must be specified."}; + auto maybe_error = + finalize_propagation_styles(result, config, *result.logger); + if (!maybe_error) { + return maybe_error.error(); } result.report_hostname = config.report_hostname; diff --git a/src/datadog/tracer_config.h b/src/datadog/tracer_config.h index f49fb672..2916aec0 100644 --- a/src/datadog/tracer_config.h +++ b/src/datadog/tracer_config.h @@ -7,11 +7,12 @@ #include #include #include +#include #include "datadog_agent_config.h" #include "error.h" #include "expected.h" -#include "propagation_styles.h" +#include "propagation_style.h" #include "span_defaults.h" #include "span_sampler_config.h" #include "trace_sampler_config.h" @@ -59,15 +60,20 @@ struct TracerConfig { // `injection_styles` indicates with which tracing systems trace propagation // will be compatible when injecting (sending) trace context. - // `injection_styles` is overridden by the `DD_PROPAGATION_STYLE_INJECT` - // environment variable. - PropagationStyles injection_styles; + // All styles indicated by `injection_styles` are used for injection. + // `injection_styles` is overridden by the `DD_TRACE_PROPAGATION_STYLE_INJECT` + // and `DD_TRACE_PROPAGATION_STYLE` environment variables. + std::vector injection_styles = {PropagationStyle::DATADOG}; // `extraction_styles` indicates with which tracing systems trace propagation // will be compatible when extracting (receiving) trace context. - // `extraction_styles` is overridden by the `DD_PROPAGATION_STYLE_EXTRACT` - // environment variable. - PropagationStyles extraction_styles; + // Extraction styles are applied in the order in which they appear in + // `extraction_styles`. The first style that produces trace context or + // produces an error determines the result of extraction. + // `extraction_styles` is overridden by the + // `DD_TRACE_PROPAGATION_STYLE_EXTRACT` and `DD_TRACE_PROPAGATION_STYLE` + // environment variables. + std::vector extraction_styles = {PropagationStyle::DATADOG}; // `report_hostname` indicates whether the tracer will include the result of // `gethostname` with traces sent to the collector. @@ -109,8 +115,8 @@ class FinalizedTracerConfig { FinalizedTraceSamplerConfig trace_sampler; FinalizedSpanSamplerConfig span_sampler; - PropagationStyles injection_styles; - PropagationStyles extraction_styles; + std::vector injection_styles; + std::vector extraction_styles; bool report_hostname; std::size_t tags_header_size; diff --git a/test/span.cpp b/test/span.cpp index df491a52..b976b2de 100644 --- a/test/span.cpp +++ b/test/span.cpp @@ -375,8 +375,7 @@ TEST_CASE("injection") { config.defaults.service = "testsvc"; config.collector = std::make_shared(); config.logger = std::make_shared(); - config.injection_styles.datadog = true; - config.injection_styles.b3 = true; + config.injection_styles = {PropagationStyle::DATADOG, PropagationStyle::B3}; auto finalized_config = finalize_config(config); REQUIRE(finalized_config); @@ -447,3 +446,22 @@ TEST_CASE("injection") { } } } + +TEST_CASE("injection can be disabled using the \"none\" style") { + TracerConfig config; + config.defaults.service = "testsvc"; + config.defaults.name = "spanny"; + config.collector = std::make_shared(); + config.logger = std::make_shared(); + config.injection_styles = {PropagationStyle::NONE}; + + const auto finalized_config = finalize_config(config); + REQUIRE(finalized_config); + Tracer tracer{*finalized_config}; + + const auto span = tracer.create_span(); + MockDictWriter writer; + span.inject(writer); + const std::unordered_map empty; + REQUIRE(writer.items == empty); +} diff --git a/test/test.h b/test/test.h index 70a7078d..0c389815 100644 --- a/test/test.h +++ b/test/test.h @@ -1,9 +1,13 @@ +#pragma once + #define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #define CATCH_CONFIG_CPP17_STRING_VIEW #define CATCH_CONFIG_CPP17_VARIANT #define CATCH_CONFIG_CPP17_OPTIONAL #define CATCH_CONFIG_CPP17_BYTE +#include + #include #include #include @@ -16,3 +20,18 @@ std::ostream& operator<<(std::ostream& stream, const std::pair& item); } // namespace std + +namespace datadog { +namespace tracing { + +template +std::ostream& operator<<(std::ostream& stream, + const Expected& expected) { + if (expected) { + return stream << "?"; // don't know in general + } + return stream << expected.error(); +} + +} // namespace tracing +} // namespace datadog diff --git a/test/tracer.cpp b/test/tracer.cpp index 97e37bc5..9f0ebdc7 100644 --- a/test/tracer.cpp +++ b/test/tracer.cpp @@ -259,155 +259,82 @@ TEST_CASE("span extraction") { SECTION("extraction failures") { struct TestCase { std::string name; - bool extract_datadog; - bool extract_b3; + std::vector extraction_styles; std::unordered_map headers; // Null means "don't expect an error." Optional expected_error; }; auto test_case = GENERATE(values({ - {"no span", true, false, {}, Error::NO_SPAN_TO_EXTRACT}, + {"no span", {PropagationStyle::DATADOG}, {}, Error::NO_SPAN_TO_EXTRACT}, {"missing trace ID", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-parent-id", "456"}}, Error::MISSING_TRACE_ID}, {"missing parent span ID", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "123"}}, Error::MISSING_PARENT_SPAN_ID}, {"missing parent span ID, but it's ok because origin", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "123"}, {"x-datadog-origin", "anything"}}, nullopt}, - {"datadog and B3 agree", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-b3-traceid", "f"}, - {"x-datadog-parent-id", "14"}, - {"x-b3-spanid", "e"}}, - nullopt}, - {"datadog and B3 disagree on trace ID", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-b3-traceid", "f0"}, - {"x-datadog-parent-id", "14"}, - {"x-b3-spanid", "e"}}, - Error::INCONSISTENT_EXTRACTION_STYLES}, - {"datadog and B3 disagree on trace ID (2)", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-datadog-parent-id", "14"}, - {"x-b3-spanid", "e"}}, - Error::INCONSISTENT_EXTRACTION_STYLES}, - {"datadog and B3 disagree on parent ID", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-b3-traceid", "f"}, - {"x-datadog-parent-id", "13"}, - {"x-b3-spanid", "e"}}, - Error::INCONSISTENT_EXTRACTION_STYLES}, - {"datadog and B3 disagree on parent ID (2)", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-b3-traceid", "f"}, - {"x-datadog-parent-id", "13"}}, - Error::INCONSISTENT_EXTRACTION_STYLES}, - {"datadog and B3 disagree on sampling priority", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-b3-traceid", "f"}, - {"x-datadog-parent-id", "14"}, - {"x-b3-spanid", "e"}, - {"x-datadog-sampling-priority", "2"}, - {"x-b3-sampled", "1"}}, - Error::INCONSISTENT_EXTRACTION_STYLES}, - {"datadog and B3 disagree on sampling priority (2)", - true, - true, - {{"x-datadog-trace-id", "15"}, - {"x-b3-traceid", "f"}, - {"x-datadog-parent-id", "14"}, - {"x-b3-spanid", "e"}, - {"x-datadog-sampling-priority", "2"}}, - Error::INCONSISTENT_EXTRACTION_STYLES}, {"bad x-datadog-trace-id", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "f"}, {"x-datadog-parent-id", "456"}}, Error::INVALID_INTEGER}, {"bad x-datadog-trace-id (2)", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "99999999999999999999999999"}, {"x-datadog-parent-id", "456"}}, Error::OUT_OF_RANGE_INTEGER}, {"bad x-datadog-parent-id", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-parent-id", "f"}, {"x-datadog-trace-id", "456"}}, Error::INVALID_INTEGER}, {"bad x-datadog-parent-id (2)", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-parent-id", "99999999999999999999999999"}, {"x-datadog-trace-id", "456"}}, Error::OUT_OF_RANGE_INTEGER}, {"bad x-datadog-sampling-priority", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-parent-id", "123"}, {"x-datadog-trace-id", "456"}, {"x-datadog-sampling-priority", "keep"}}, Error::INVALID_INTEGER}, {"bad x-datadog-sampling-priority (2)", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-parent-id", "123"}, {"x-datadog-trace-id", "456"}, {"x-datadog-sampling-priority", "99999999999999999999999999"}}, Error::OUT_OF_RANGE_INTEGER}, {"bad x-b3-traceid", - false, - true, + {PropagationStyle::B3}, {{"x-b3-traceid", "0xdeadbeef"}, {"x-b3-spanid", "def"}}, Error::INVALID_INTEGER}, {"bad x-b3-traceid (2)", - false, - true, + {PropagationStyle::B3}, {{"x-b3-traceid", "ffffffffffffffffffffffffffffff"}, {"x-b3-spanid", "def"}}, Error::OUT_OF_RANGE_INTEGER}, {"bad x-b3-spanid", - false, - true, + {PropagationStyle::B3}, {{"x-b3-spanid", "0xdeadbeef"}, {"x-b3-traceid", "def"}}, Error::INVALID_INTEGER}, {"bad x-b3-spanid (2)", - false, - true, + {PropagationStyle::B3}, {{"x-b3-spanid", "ffffffffffffffffffffffffffffff"}, {"x-b3-traceid", "def"}}, Error::OUT_OF_RANGE_INTEGER}, {"bad x-b3-sampled", - false, - true, + {PropagationStyle::B3}, {{"x-b3-traceid", "abc"}, {"x-b3-spanid", "def"}, {"x-b3-sampled", "true"}}, Error::INVALID_INTEGER}, {"bad x-b3-sampled (2)", - false, - true, + {PropagationStyle::B3}, {{"x-b3-traceid", "abc"}, {"x-b3-spanid", "def"}, {"x-b3-sampled", "99999999999999999999999999"}}, @@ -416,8 +343,7 @@ TEST_CASE("span extraction") { CAPTURE(test_case.name); - config.extraction_styles.datadog = test_case.extract_datadog; - config.extraction_styles.b3 = test_case.extract_b3; + config.extraction_styles = test_case.extraction_styles; auto finalized_config = finalize_config(config); REQUIRE(finalized_config); Tracer tracer{*finalized_config}; @@ -449,8 +375,7 @@ TEST_CASE("span extraction") { SECTION("extracted span has the expected properties") { struct TestCase { std::string name; - bool extract_datadog; - bool extract_b3; + std::vector extraction_styles; std::unordered_map headers; std::uint64_t expected_trace_id; Optional expected_parent_id; @@ -459,8 +384,7 @@ TEST_CASE("span extraction") { auto test_case = GENERATE(values({ {"datadog style", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "123"}, {"x-datadog-parent-id", "456"}, {"x-datadog-sampling-priority", "2"}}, @@ -468,22 +392,19 @@ TEST_CASE("span extraction") { 456, 2}, {"datadog style without sampling priority", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "123"}, {"x-datadog-parent-id", "456"}}, 123, 456, nullopt}, {"datadog style without sampling priority and without parent ID", - true, - false, + {PropagationStyle::DATADOG}, {{"x-datadog-trace-id", "123"}, {"x-datadog-origin", "whatever"}}, 123, nullopt, nullopt}, {"B3 style", - false, - true, + {PropagationStyle::B3}, {{"x-b3-traceid", "abc"}, {"x-b3-spanid", "def"}, {"x-b3-sampled", "0"}}, @@ -491,40 +412,48 @@ TEST_CASE("span extraction") { 0xdef, 0}, {"B3 style without sampling priority", - false, - true, + {PropagationStyle::B3}, {{"x-b3-traceid", "abc"}, {"x-b3-spanid", "def"}}, 0xabc, 0xdef, nullopt}, - {"Datadog and B3 style together", - true, - true, + {"Datadog overriding B3", + {PropagationStyle::DATADOG, PropagationStyle::B3}, {{"x-datadog-trace-id", "255"}, {"x-datadog-parent-id", "14"}, {"x-datadog-sampling-priority", "0"}, - {"x-b3-traceid", "ff"}, - {"x-b3-spanid", "e"}, + {"x-b3-traceid", "fff"}, + {"x-b3-spanid", "ef"}, {"x-b3-sampled", "0"}}, 255, 14, 0}, - {"Datadog and B3 style together without sampling priority", - true, - true, + {"Datadog overriding B3, without sampling priority", + {PropagationStyle::DATADOG, PropagationStyle::B3}, {{"x-datadog-trace-id", "255"}, {"x-datadog-parent-id", "14"}, - {"x-b3-traceid", "ff"}, - {"x-b3-spanid", "e"}}, + {"x-b3-traceid", "fff"}, + {"x-b3-spanid", "ef"}}, 255, 14, nullopt}, + {"B3 after Datadog found no context", + {PropagationStyle::DATADOG, PropagationStyle::B3}, + {{"x-b3-traceid", "ff"}, {"x-b3-spanid", "e"}}, + 0xff, + 0xe, + nullopt}, + {"Datadog after B3 found no context", + {PropagationStyle::B3, PropagationStyle::DATADOG}, + {{"x-b3-traceid", "fff"}, {"x-b3-spanid", "ef"}}, + 0xfff, + 0xef, + nullopt}, })); CAPTURE(test_case.name); - config.extraction_styles.datadog = test_case.extract_datadog; - config.extraction_styles.b3 = test_case.extract_b3; + config.extraction_styles = test_case.extraction_styles; auto finalized_config = finalize_config(config); REQUIRE(finalized_config); Tracer tracer{*finalized_config}; @@ -552,6 +481,29 @@ TEST_CASE("span extraction") { checks(test_case, *span); } + SECTION("extraction can be disabled using the \"none\" style") { + config.extraction_styles = {PropagationStyle::NONE}; + + const auto finalized_config = finalize_config(config); + REQUIRE(finalized_config); + Tracer tracer{*finalized_config}; + const std::unordered_map headers{ + // It doesn't matter which headers are present. + // The "none" extraction style will not inspect them, and will return + // the "no span to extract" error. + {"X-Datadog-Trace-ID", "foo"}, + {"X-Datadog-Parent-ID", "bar"}, + {"X-Datadog-Sampling-Priority", "baz"}, + {"X-B3-TraceID", "foo"}, + {"X-B3-SpanID", "bar"}, + {"X-B3-Sampled", "baz"}, + }; + MockDictReader reader{headers}; + const auto result = tracer.extract_span(reader); + REQUIRE(!result); + REQUIRE(result.error().code == Error::NO_SPAN_TO_EXTRACT); + } + SECTION("x-datadog-tags") { auto finalized_config = finalize_config(config); REQUIRE(finalized_config); diff --git a/test/tracer_config.cpp b/test/tracer_config.cpp index bbf9a44f..27e4bb85 100644 --- a/test/tracer_config.cpp +++ b/test/tracer_config.cpp @@ -1,11 +1,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -29,19 +30,8 @@ namespace datadog { namespace tracing { -std::ostream& operator<<(std::ostream& stream, - const PropagationStyles& styles) { - stream << '{'; - const char* separator = ""; - if (styles.datadog) { - stream << "Datadog"; - separator = ", "; - } - if (styles.b3) { - stream << separator << "B3"; - separator = ", "; - } - return stream << '}'; +std::ostream& operator<<(std::ostream& stream, PropagationStyle style) { + return stream << to_json(style).dump(); } } // namespace tracing @@ -985,29 +975,64 @@ TEST_CASE("TracerConfig propagation styles") { TracerConfig config; config.defaults.service = "testsvc"; + SECTION("DD_TRACE_PROPAGATION_STYLE overrides defaults") { + const EnvGuard guard{"DD_TRACE_PROPAGATION_STYLE", "B3"}; + auto finalized = finalize_config(config); + REQUIRE(finalized); + + const std::vector expected_styles = { + PropagationStyle::B3}; + + REQUIRE(finalized->injection_styles == expected_styles); + REQUIRE(finalized->extraction_styles == expected_styles); + } + SECTION("injection_styles") { SECTION("defaults to just Datadog") { auto finalized = finalize_config(config); REQUIRE(finalized); - REQUIRE(finalized->injection_styles.datadog); - REQUIRE(!finalized->injection_styles.b3); + const std::vector expected_styles = { + PropagationStyle::DATADOG}; + REQUIRE(finalized->injection_styles == expected_styles); } SECTION("need at least one") { - config.injection_styles.datadog = false; - config.injection_styles.b3 = false; + config.injection_styles.clear(); auto finalized = finalize_config(config); REQUIRE(!finalized); REQUIRE(finalized.error().code == Error::MISSING_SPAN_INJECTION_STYLE); } - SECTION("DD_PROPAGATION_STYLE_INJECT") { + SECTION("DD_TRACE_PROPAGATION_STYLE_INJECT") { SECTION("overrides injection_styles") { - const EnvGuard guard{"DD_PROPAGATION_STYLE_INJECT", "B3"}; + const EnvGuard guard{"DD_TRACE_PROPAGATION_STYLE_INJECT", "B3"}; + auto finalized = finalize_config(config); + REQUIRE(finalized); + const std::vector expected_styles = { + PropagationStyle::B3}; + REQUIRE(finalized->injection_styles == expected_styles); + } + + SECTION("overrides DD_PROPAGATION_STYLE_INJECT") { + const EnvGuard guard1{"DD_TRACE_PROPAGATION_STYLE_INJECT", "B3"}; + const EnvGuard guard2{"DD_PROPAGATION_STYLE_INJECT", "Datadog"}; + config.logger = std::make_shared(); // suppress warning + auto finalized = finalize_config(config); + REQUIRE(finalized); + const std::vector expected_styles = { + PropagationStyle::B3}; + REQUIRE(finalized->injection_styles == expected_styles); + } + + SECTION("overrides DD_TRACE_PROPAGATION_STYLE") { + const EnvGuard guard1{"DD_TRACE_PROPAGATION_STYLE_INJECT", "B3"}; + const EnvGuard guard2{"DD_TRACE_PROPAGATION_STYLE", "Datadog"}; + config.logger = std::make_shared(); // suppress warning auto finalized = finalize_config(config); REQUIRE(finalized); - REQUIRE(!finalized->injection_styles.datadog); - REQUIRE(finalized->injection_styles.b3); + const std::vector expected_styles = { + PropagationStyle::B3}; + REQUIRE(finalized->injection_styles == expected_styles); } SECTION("parsing") { @@ -1015,32 +1040,39 @@ TEST_CASE("TracerConfig propagation styles") { int line; std::string env_value; Optional expected_error; - PropagationStyles expected_styles = PropagationStyles{}; + std::vector expected_styles = {}; }; + // brevity + const auto datadog = PropagationStyle::DATADOG, + b3 = PropagationStyle::B3, none = PropagationStyle::NONE; // clang-format off auto test_case = GENERATE(values({ - {__LINE__, "Datadog", x, {true, false}}, - {__LINE__, "DaTaDoG", x, {true, false}}, - {__LINE__, "B3", x, {false, true}}, - {__LINE__, "b3", x, {false, true}}, - {__LINE__, "Datadog B3", x, {true, true}}, - {__LINE__, "B3 Datadog", x, {true, true}}, - {__LINE__, "b3 datadog", x, {true, true}}, - {__LINE__, "b3, datadog", x, {true, true}}, - {__LINE__, "b3,datadog", x, {true, true}}, - {__LINE__, "b3, datadog", x, {true, true}}, + {__LINE__, "Datadog", x, {datadog}}, + {__LINE__, "DaTaDoG", x, {datadog}}, + {__LINE__, "B3", x, {b3}}, + {__LINE__, "b3", x, {b3}}, + {__LINE__, "b3MULTI", x, {b3}}, + {__LINE__, "b3, b3multi", Error::DUPLICATE_PROPAGATION_STYLE }, + {__LINE__, "Datadog B3", x, {datadog, b3}}, + {__LINE__, "Datadog B3 none", x, {datadog, b3, none}}, + {__LINE__, "NONE", x, {none}}, + {__LINE__, "B3 Datadog", x, {b3, datadog}}, + {__LINE__, "b3 datadog", x, {b3, datadog}}, + {__LINE__, "b3, datadog", x, {b3, datadog}}, + {__LINE__, "b3,datadog", x, {b3, datadog}}, + {__LINE__, "b3, datadog", x, {b3, datadog}}, {__LINE__, "b3,,datadog", Error::UNKNOWN_PROPAGATION_STYLE}, {__LINE__, "b3,datadog,w3c", Error::UNKNOWN_PROPAGATION_STYLE}, - {__LINE__, "b3,datadog,datadog", x, {true, true}}, - {__LINE__, " b3 b3 b3, b3 , b3, b3, b3 , b3 b3 b3 ", x, {false, true}}, + {__LINE__, "b3,datadog,datadog", Error::DUPLICATE_PROPAGATION_STYLE}, + {__LINE__, " b3 b3 b3, b3 , b3, b3, b3 , b3 b3 b3 ", Error::DUPLICATE_PROPAGATION_STYLE}, })); // clang-format on CAPTURE(test_case.line); CAPTURE(test_case.env_value); - const EnvGuard guard{"DD_PROPAGATION_STYLE_INJECT", + const EnvGuard guard{"DD_TRACE_PROPAGATION_STYLE_INJECT", test_case.env_value}; auto finalized = finalize_config(config); if (test_case.expected_error) { @@ -1048,10 +1080,7 @@ TEST_CASE("TracerConfig propagation styles") { REQUIRE(finalized.error().code == *test_case.expected_error); } else { REQUIRE(finalized); - REQUIRE(finalized->injection_styles.datadog == - test_case.expected_styles.datadog); - REQUIRE(finalized->injection_styles.b3 == - test_case.expected_styles.b3); + REQUIRE(finalized->injection_styles == test_case.expected_styles); } } } @@ -1062,25 +1091,48 @@ TEST_CASE("TracerConfig propagation styles") { SECTION("defaults to just Datadog") { auto finalized = finalize_config(config); REQUIRE(finalized); - REQUIRE(finalized->extraction_styles.datadog); - REQUIRE(!finalized->extraction_styles.b3); + const std::vector expected_styles = { + PropagationStyle::DATADOG}; + REQUIRE(finalized->extraction_styles == expected_styles); } SECTION("need at least one") { - config.extraction_styles.datadog = false; - config.extraction_styles.b3 = false; + config.extraction_styles.clear(); auto finalized = finalize_config(config); REQUIRE(!finalized); REQUIRE(finalized.error().code == Error::MISSING_SPAN_EXTRACTION_STYLE); } - SECTION("DD_PROPAGATION_STYLE_EXTRACT") { + SECTION("DD_TRACE_PROPAGATION_STYLE_EXTRACT") { SECTION("overrides extraction_styles") { - const EnvGuard guard{"DD_PROPAGATION_STYLE_EXTRACT", "B3"}; + const EnvGuard guard{"DD_TRACE_PROPAGATION_STYLE_EXTRACT", "B3"}; auto finalized = finalize_config(config); REQUIRE(finalized); - REQUIRE(!finalized->extraction_styles.datadog); - REQUIRE(finalized->extraction_styles.b3); + const std::vector expected_styles = { + PropagationStyle::B3}; + REQUIRE(finalized->extraction_styles == expected_styles); + } + + SECTION("overrides DD_PROPAGATION_STYLE_EXTRACT") { + const EnvGuard guard1{"DD_TRACE_PROPAGATION_STYLE_EXTRACT", "B3"}; + const EnvGuard guard2{"DD_PROPAGATION_STYLE_EXTRACT", "Datadog"}; + config.logger = std::make_shared(); // suppress warning + auto finalized = finalize_config(config); + REQUIRE(finalized); + const std::vector expected_styles = { + PropagationStyle::B3}; + REQUIRE(finalized->extraction_styles == expected_styles); + } + + SECTION("overrides DD_TRACE_PROPAGATION_STYLE") { + const EnvGuard guard1{"DD_TRACE_PROPAGATION_STYLE_EXTRACT", "B3"}; + const EnvGuard guard2{"DD_TRACE_PROPAGATION_STYLE", "Datadog"}; + config.logger = std::make_shared(); // suppress warning + auto finalized = finalize_config(config); + REQUIRE(finalized); + const std::vector expected_styles = { + PropagationStyle::B3}; + REQUIRE(finalized->extraction_styles == expected_styles); } // It's the same as for injection styles, so let's omit most of the @@ -1094,4 +1146,53 @@ TEST_CASE("TracerConfig propagation styles") { } } } + + SECTION("warn if one env var overrides another") { + const auto logger = std::make_shared(); + config.logger = logger; + const auto ts = "DD_TRACE_PROPAGATION_STYLE"; + const auto tse = "DD_TRACE_PROPAGATION_STYLE_EXTRACT"; + const auto se = "DD_PROPAGATION_STYLE_EXTRACT"; + const auto tsi = "DD_TRACE_PROPAGATION_STYLE_INJECT"; + const auto si = "DD_PROPAGATION_STYLE_INJECT"; + const char* const vars[] = {ts, tse, se, tsi, si}; + constexpr auto n = sizeof(vars) / sizeof(vars[0]); + // clang-format off + const bool x = false; // ignored values + const bool expect_warning[n][n] = { + // ts tse se tsi si + // --- --- --- --- --- + /* ts */{ x, true, true, true, true }, + + /* tse */{ x, x, true, false, false }, + + /* se */{ x, x, x, false, false }, + + /* tsi */{ x, x, x, x, true }, + + /* si */{ x, x, x, x, x }, + }; + // clang-format on + for (std::size_t i = 0; i < n; ++i) { + for (std::size_t j = i + 1; j < n; ++j) { + CAPTURE(i); + CAPTURE(vars[i]); + CAPTURE(j); + CAPTURE(vars[j]); + CAPTURE(expect_warning[i][j]); + const EnvGuard guard1{vars[i], "B3"}; + const EnvGuard guard2{vars[j], "B3"}; + const auto finalized_config = finalize_config(config); + REQUIRE(finalized_config); + if (expect_warning[i][j]) { + REQUIRE(logger->error_count() == 1); + REQUIRE(logger->first_error().code == + Error::MULTIPLE_PROPAGATION_STYLE_ENVIRONMENT_VARIABLES); + } else { + REQUIRE(logger->error_count() == 0); + } + logger->entries.clear(); + } + } + } }