Skip to content

W3C-style trace context propagation#13

Merged
dgoffredo merged 29 commits intomainfrom
david.goffredo/w3c-propagation
Jan 13, 2023
Merged

W3C-style trace context propagation#13
dgoffredo merged 29 commits intomainfrom
david.goffredo/w3c-propagation

Conversation

@dgoffredo
Copy link
Copy Markdown
Contributor

@dgoffredo dgoffredo commented Dec 20, 2022

This implements W3C-style trace context propagation using the "traceparent" and "tracestate" headers. It is based on a internal design document.

It's an extension of work done previously in #12.

In addition to adding the PropagationStyle::W3C, this work also resulted in the following changes:

  • struct ExtractedData was factored out into its own extracted_data.{h,cpp}.
  • The hex function was factored out into its own hex.{h,cpp}.
  • bin/check was added, and bin/test modified, for minor development convenience.
  • The representation of trace tags is now vector<pair<string, string>> instead of the previous unordered_map<string, string>. This made unit tests simpler and more honest, and the preservation of order is a nice property to have, likely without any performance penalty.
  • Trailing whitespace was removed from the code.

@dgoffredo dgoffredo force-pushed the david.goffredo/w3c-propagation branch 5 times, most recently from 8a8a7b6 to 343d9ea Compare December 21, 2022 19:53
@dgoffredo dgoffredo marked this pull request as ready for review December 22, 2022 04:18
@dgoffredo dgoffredo requested a review from cgilmour December 22, 2022 04:18
@dgoffredo dgoffredo force-pushed the david.goffredo/w3c-propagation branch from 98a9a8e to c1d099f Compare January 9, 2023 23:17
@dgoffredo dgoffredo force-pushed the david.goffredo/w3c-propagation branch from 5f82e62 to f789c1c Compare January 10, 2023 21:49
Copy link
Copy Markdown
Contributor

@cgilmour cgilmour left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm marking this as approved for now, with some questions in the comments.
Some extra time would be needed to dig into the implementation details / cross-check with opentelemtry specs and other implementations.

Especially with regard to extraction, I think as other implementations are being completed, it'd be good to have some interop tests with other tracers developed by datadog and also external implementations.

In that circumstance, what's the overall impact on tracing if we received this header but didn't perfectly comprehend it?

// without any leading zeroes.
template <typename Integer>
std::string hex(Integer value) {
// 4 bits per hex digit char, and then +1 char for possible minus sign
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Negative hex values shouldn't be a thing here, since it's intended to be an encoding of a bit pattern (more like a hexdump) instead of a representation of a numeric value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function supports any integral type, so I had to accommodate the minus sign.

In a more recent PR, I constrained the type to be unsigned and added a "padded" variant of the function: https://github.com/DataDog/dd-trace-cpp/pull/17/files#diff-666374b8256a8b91fa9a3a030a39c3f75cfafe26d044c6c9c7d9e39db6c895f8R32-R51

Would you like me to backport that change on this PR?

message += std::to_string(encoded_trace_tags.size());
message += " bytes.";
logger.log_error(message);
local_root_tags[tags::internal::propagation_error] = "inject_max_size";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why on local-root instead of the span specifically?
What if the same span is propagated more than once?
What if multiple child spans of the local-root experienced the same error?

Copy link
Copy Markdown
Contributor Author

@dgoffredo dgoffredo Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tags::internal::propagation_error is specified in the horizontal propagation RFC. There it's defined to be set on the local root span, and implementations are allowed to either keep the first error or to keep the last error. I chose the latter.

This section of code refactors behavior that existed before this PR.

const Optional<std::string>& hostname, Optional<std::string> origin,
std::size_t tags_header_max_size,
std::unordered_map<std::string, std::string> trace_tags,
std::vector<std::pair<std::string, std::string>> trace_tags,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of parameters for a constructor. Just sayin.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I could create a struct to hold them, but I decided not to. What do you think?

// - equal to one of the `disallowed_characters`.
//
// `verboten` is used with `std::replace_if` to sanitize field values within the
// tracestate header.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The entire header or just our part of it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just our part of it.

result += *additional_datadog_w3c_tracestate;
}

const std::size_t max_size = 256;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an arbitrary size or is it defined somewhere?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's defined in our W3C propagation RFC. It's not configurable because it is derived from the W3C definition itself.

@dgoffredo
Copy link
Copy Markdown
Contributor Author

Thanks for the review.

Especially with regard to extraction, I think as other implementations are being completed, it'd be good to have some interop tests with other tracers developed by datadog and also external implementations.

There is or will be system tests for this feature. As a prerequisite to that, we'd need to integrate the tracer with the system tests framework.

In that circumstance, what's the overall impact on tracing if we received this header but didn't perfectly comprehend it?

If we fail to extract trace context from the W3C headers, we try the next configured extraction style (Datadog by default). If no trace context can be extracted in any configured style, extraction fails.

@dgoffredo dgoffredo merged commit 36d1b60 into main Jan 13, 2023
@dgoffredo dgoffredo deleted the david.goffredo/w3c-propagation branch January 13, 2023 15:53
cataphract pushed a commit to cataphract/dd-trace-cpp that referenced this pull request Mar 28, 2024
* update example to support new image naming scheme

* working on adding example/ to CircleCI

* let's make an example request in CircleCI

* no bind mounts allowed

* when it doubt, add more fudge

* simplify the example in the CI

* don't make readme files executable

* shellcheck

* CircleCI no likely but not say why

* no need for python in the example

* oops: edited the wrong job

* circleci doesn't like forward slashes in job names
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants