-
Notifications
You must be signed in to change notification settings - Fork 15
feat: add baggage API #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
6a00277
feat: add baggage API
dmehala 58c51ba
perf: customer parser (~1.5x faster)
dmehala d864fb5
fix: uninit values
dmehala d9e5d49
remove slow std::isspace
dmehala 505ca62
wip
b8fcb57
code review
4328f39
format
dmehala 5b8f0b9
code review
dmehala 4ccdb2e
Merge branch 'main' into dmehala/baggage-api
dmehala File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| add_subdirectory(baggage) | ||
| add_subdirectory(hasher) | ||
| add_subdirectory(http-server) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| add_executable(baggage-example main.cpp) | ||
| target_link_libraries(baggage-example dd_trace_cpp-static) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| #include <datadog/dict_reader.h> | ||
| #include <datadog/tracer.h> | ||
|
|
||
| #include <iostream> | ||
|
|
||
| namespace dd = datadog::tracing; | ||
|
|
||
| struct CinReader : public dd::DictReader { | ||
| std::string input; | ||
|
|
||
| dd::Optional<dd::StringView> lookup(dd::StringView key) const override { | ||
| return input; | ||
| } | ||
|
|
||
| void visit( | ||
| const std::function<void(dd::StringView key, dd::StringView value)>& | ||
| visitor) const override{}; | ||
| }; | ||
|
|
||
| std::istream& operator>>(std::istream& is, CinReader& reader) { | ||
| is >> reader.input; | ||
| return is; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, dd::Baggage::Error error) { | ||
| using dd::Baggage; | ||
| switch (error.code) { | ||
| case Baggage::Error::MISSING_HEADER: | ||
| os << "missing `baggage` header"; | ||
| break; | ||
| case Baggage::Error::MALFORMED_BAGGAGE_HEADER: { | ||
| os << "malformed `baggage` header"; | ||
| if (error.pos) { | ||
| os << " at position " << *error.pos; | ||
| } | ||
| } break; | ||
| case Baggage::Error::MAXIMUM_CAPACITY_REACHED: | ||
| os << "maximum number of bagge items reached"; | ||
| break; | ||
| case Baggage::Error::MAXIMUM_BYTES_REACHED: | ||
| os << "maximum amount of bytes written"; | ||
| break; | ||
| default: | ||
| os << "unknown error code"; | ||
| break; | ||
| } | ||
| return os; | ||
| } | ||
|
|
||
| int main() { | ||
| dd::TracerConfig cfg; | ||
| cfg.log_on_startup = false; | ||
| cfg.telemetry.enabled = false; | ||
| cfg.agent.remote_configuration_enabled = false; | ||
| const auto finalized_cfg = datadog::tracing::finalize_config(cfg); | ||
| if (auto error = finalized_cfg.if_error()) { | ||
| std::cerr << "Failed to initialize the tracer: " << error->message | ||
| << std::endl; | ||
| return error->code; | ||
| } | ||
|
|
||
| dd::Tracer tracer(*finalized_cfg); | ||
|
|
||
| std::cout | ||
| << "This program demonstrates how to use baggage, a feature that allows " | ||
| "metadata (key-value pairs) to be attached to a request and " | ||
| "propagated across services.\n" | ||
| "Baggage can be useful for passing contextual information, such as " | ||
| "user IDs, session tokens, or request attributes, between different " | ||
| "components of a distributed system.\n\n" | ||
| "This example lets you input baggage values, validate them and " | ||
| "displays the baggage content parsed.\n" | ||
| "You can enter baggage manually or provide it through a file, try:\n" | ||
| "- k1=v1,k2=v2\n" | ||
| "- ,invalid=input\n" | ||
| "or ./baggage-example < list-of-baggages.txt\n\n"; | ||
|
|
||
| CinReader reader; | ||
| std::cout << "Enter baggage (or 'CTRL+C' to quit): "; | ||
| while (std::getline(std::cin, reader.input)) { | ||
| auto baggage = tracer.extract_baggage(reader); | ||
| if (!baggage) { | ||
| std::cout << "Error parsing \"" << reader.input | ||
| << "\": " << baggage.error() << ".\n"; | ||
| } else { | ||
| std::cout << "Baggage key-value parsed: \n"; | ||
| baggage->visit([](dd::StringView key, dd::StringView value) { | ||
| std::cout << key << ": " << value << std::endl; | ||
| }); | ||
| } | ||
|
|
||
| std::cout << "\nEnter baggage (or 'CTRL+C' to quit): "; | ||
| } | ||
| return 0; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| add_subdirectory(base64) | ||
| add_subdirectory(tracing) | ||
| add_subdirectory(w3c-propagation) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| add_executable(baggage-fuzz baggage.cpp) | ||
|
|
||
| add_dependencies(baggage-fuzz dd_trace_cpp-static) | ||
|
|
||
| target_include_directories(baggage-fuzz | ||
| PRIVATE | ||
| ${CMAKE_SOURCE_DIR}/src | ||
| ) | ||
|
|
||
| target_link_libraries(baggage-fuzz dd_trace_cpp-static) | ||
|
|
||
| add_target_to_group(baggage-fuzz dd_trace_cpp-fuzzers) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| #include <datadog/baggage.h> | ||
| #include <datadog/dict_reader.h> | ||
| #include <datadog/string_view.h> | ||
|
|
||
| #include <cstdint> | ||
|
|
||
| namespace dd = datadog::tracing; | ||
|
|
||
| class MapReader : public dd::DictReader { | ||
| std::unordered_map<std::string, std::string> map_; | ||
|
|
||
| public: | ||
| ~MapReader() override = default; | ||
|
|
||
| MapReader(std::unordered_map<std::string, std::string> map) | ||
| : map_(std::move(map)) {} | ||
|
|
||
| dd::Optional<dd::StringView> lookup(dd::StringView key) const override { | ||
| auto it = map_.find(std::string(key)); | ||
| if (it == map_.cend()) return dd::nullopt; | ||
|
|
||
| return it->second; | ||
| } | ||
|
|
||
| void visit(const std::function<void(dd::StringView key, | ||
| dd::StringView value)>&) const override{}; | ||
| }; | ||
|
|
||
| extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, size_t size) { | ||
| MapReader reader({{"baggage", std::string((const char*)data, size)}}); | ||
| dd::Baggage::extract(reader); | ||
| return 0; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| #pragma once | ||
|
|
||
| #include <datadog/dict_reader.h> | ||
| #include <datadog/dict_writer.h> | ||
| #include <datadog/expected.h> | ||
| #include <datadog/optional.h> | ||
| #include <datadog/string_view.h> | ||
|
|
||
| #include <string> | ||
| #include <unordered_map> | ||
|
|
||
| namespace datadog { | ||
| namespace tracing { | ||
|
|
||
| /// OpenTelemetry-like implementation of the Baggage concept. | ||
| /// Baggage is a key-value store meant to propagate data across services and | ||
| /// processes boundaries. | ||
| /// | ||
| /// Baggage are extracted from any tracing context implementing the `DictReader` | ||
| /// interface using `Baggage::extract`. | ||
| /// | ||
| /// Baggages are injected to any tracing context implementing the `DictWriter` | ||
| /// interface using the `inject` method. | ||
| class Baggage { | ||
| public: | ||
| struct Error final { | ||
| enum Code : char { | ||
| /// Baggage propagation is disabled. This may be due to one of the | ||
| /// following | ||
| /// reasons: | ||
| /// - `baggage` is not set as an extraction or injection propagation | ||
| /// style. | ||
| /// - The maximum number of items is less than 0. | ||
| /// - The number of bytes is less than 3. | ||
| DISABLED, | ||
| MISSING_HEADER, | ||
| MALFORMED_BAGGAGE_HEADER, | ||
| MAXIMUM_CAPACITY_REACHED, | ||
| MAXIMUM_BYTES_REACHED, | ||
| }; | ||
| Code code; | ||
| Optional<size_t> pos; | ||
|
|
||
| Error(Code in_code) : code(in_code), pos(nullopt) {} | ||
| Error(Code in_code, size_t position) : code(in_code), pos(position) {} | ||
| }; | ||
|
|
||
| struct Options final { | ||
| size_t max_bytes; | ||
| size_t max_items; | ||
| }; | ||
|
|
||
| static constexpr size_t default_max_capacity = 64; | ||
| static constexpr Options default_options{2048, default_max_capacity}; | ||
|
|
||
| /// Extracts a Baggage instance from a `DictReader` and creates a Baggage | ||
| /// instance if no errors are encounters . | ||
| /// | ||
| /// @param `reader` The input `DictReader` from which to extract the data. | ||
| /// @return A `Baggage` instance or an `Error`. | ||
| static Expected<Baggage, Error> extract(const DictReader& reader); | ||
|
|
||
| /// Initializes an empty Baggage with the default maximum capacity. | ||
| Baggage() = default; | ||
|
|
||
| /// Initializes an empty Baggage instance with the given maximum capacity. | ||
| /// | ||
| /// @param `max_capacity` The maximum capacity for this Baggage instance. | ||
| Baggage(size_t max_capacity); | ||
|
|
||
| /// Initializes a Baggage instance using the provided unordered_map of | ||
| /// key-value pairs. The maximum capacity can also be specified. | ||
| /// | ||
| /// @param `baggage_map` The map containing key-value pairs to initialize the | ||
| /// Baggage. | ||
| /// @param `max_capacity` The maximum capacity for this Baggage instance. | ||
| Baggage(std::unordered_map<std::string, std::string>, | ||
| size_t max_capacity = default_max_capacity); | ||
|
|
||
| /// Checks if the Baggage contains a specified key. | ||
| /// | ||
| /// @param `key` The key to check. | ||
| /// @return `true` if the key exists in the Baggage; otherwise, `false`. | ||
| bool contains(StringView key) const; | ||
|
|
||
| /// Retrieves the value associated with a specified key. | ||
| /// | ||
| /// @param `key` The key to retrieve the value for. | ||
| /// @return An `Optional<StringView>` containing the value if the key exists, | ||
| /// or an empty Optional if the key is not found. | ||
| Optional<StringView> get(StringView key) const; | ||
|
|
||
| /// Adds a key-value pair to the Baggage. | ||
| /// | ||
| /// This function will attempt to add the given key-value pair to the Baggage. | ||
| /// If the maximum capacity has been reached, the insertion will fail. | ||
| /// If a `key` already exists, its value will be overwritten with `value`. | ||
| /// | ||
| /// @param `key` The key to insert. | ||
| /// @param `value` The value to associate with the key. | ||
| /// @return `true` if the key-value pair was successfully added; `false` if | ||
| /// the maximum capacity was reached. | ||
| bool set(std::string key, std::string value); | ||
|
|
||
| /// Removes the key-value pair corresponding to the specified key. | ||
| /// | ||
| /// @param `key` The key to remove from the Baggage. | ||
| void remove(StringView key); | ||
|
|
||
| /// Removes all key-value pair. | ||
| void clear(); | ||
|
|
||
| /// Retrieves the number of items stored. | ||
| size_t size() const; | ||
|
|
||
| /// Returns whether any items are stored. | ||
| bool empty() const; | ||
|
|
||
| /// Visits each key-value pair in the Baggage and invoke the provided | ||
| /// visitor function for each key-value pair in the Baggage. | ||
| /// | ||
| /// @param `visitor` A function object that will be called for each | ||
| /// key-value pair. | ||
| void visit(std::function<void(StringView, StringView)>&& visitor); | ||
|
|
||
| /// Injects the Baggage data into a `DictWriter` with the constraint that | ||
| /// the amount of bytes written does not exceed the specified maximum byte | ||
| /// limit. | ||
| /// | ||
| /// @param `writer` The DictWriter to inject the data into. | ||
| /// @param `opts` Injection options. | ||
| /// @return An `Expected<void>`, which may either succeed or contain an | ||
| /// error. | ||
| Expected<void> inject(DictWriter& writer, | ||
| const Options& opts = default_options) const; | ||
|
|
||
| /// Equality operator for comparing two Baggage instances. | ||
| inline bool operator==(const Baggage& rhs) const { | ||
| return baggage_ == rhs.baggage_; | ||
| } | ||
|
|
||
| private: | ||
| const size_t max_capacity_ = Baggage::default_max_capacity; | ||
| std::unordered_map<std::string, std::string> baggage_; | ||
| }; | ||
|
|
||
| } // namespace tracing | ||
| } // namespace datadog | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.