|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <datadog/dict_reader.h> |
| 4 | +#include <datadog/dict_writer.h> |
| 5 | +#include <datadog/expected.h> |
| 6 | +#include <datadog/optional.h> |
| 7 | +#include <datadog/string_view.h> |
| 8 | + |
| 9 | +#include <string> |
| 10 | +#include <unordered_map> |
| 11 | + |
| 12 | +namespace datadog { |
| 13 | +namespace tracing { |
| 14 | + |
| 15 | +/// OpenTelemetry-like implementation of the Baggage concept. |
| 16 | +/// Baggage is a key-value store meant to propagate data across services and |
| 17 | +/// processes boundaries. |
| 18 | +/// |
| 19 | +/// Baggage are extracted from any tracing context implementing the `DictReader` |
| 20 | +/// interface using `Baggage::extract`. |
| 21 | +/// |
| 22 | +/// Baggages are injected to any tracing context implementing the `DictWriter` |
| 23 | +/// interface using the `inject` method. |
| 24 | +class Baggage { |
| 25 | + public: |
| 26 | + struct Error final { |
| 27 | + enum Code : char { |
| 28 | + /// Baggage propagation is disabled. This may be due to one of the |
| 29 | + /// following |
| 30 | + /// reasons: |
| 31 | + /// - `baggage` is not set as an extraction or injection propagation |
| 32 | + /// style. |
| 33 | + /// - The maximum number of items is less than 0. |
| 34 | + /// - The number of bytes is less than 3. |
| 35 | + DISABLED, |
| 36 | + MISSING_HEADER, |
| 37 | + MALFORMED_BAGGAGE_HEADER, |
| 38 | + MAXIMUM_CAPACITY_REACHED, |
| 39 | + MAXIMUM_BYTES_REACHED, |
| 40 | + }; |
| 41 | + Code code; |
| 42 | + Optional<size_t> pos; |
| 43 | + |
| 44 | + Error(Code in_code) : code(in_code), pos(nullopt) {} |
| 45 | + Error(Code in_code, size_t position) : code(in_code), pos(position) {} |
| 46 | + }; |
| 47 | + |
| 48 | + struct Options final { |
| 49 | + size_t max_bytes; |
| 50 | + size_t max_items; |
| 51 | + }; |
| 52 | + |
| 53 | + static constexpr size_t default_max_capacity = 64; |
| 54 | + static constexpr Options default_options{2048, default_max_capacity}; |
| 55 | + |
| 56 | + /// Extracts a Baggage instance from a `DictReader` and creates a Baggage |
| 57 | + /// instance if no errors are encounters . |
| 58 | + /// |
| 59 | + /// @param `reader` The input `DictReader` from which to extract the data. |
| 60 | + /// @return A `Baggage` instance or an `Error`. |
| 61 | + static Expected<Baggage, Error> extract(const DictReader& reader); |
| 62 | + |
| 63 | + /// Initializes an empty Baggage with the default maximum capacity. |
| 64 | + Baggage() = default; |
| 65 | + |
| 66 | + /// Initializes an empty Baggage instance with the given maximum capacity. |
| 67 | + /// |
| 68 | + /// @param `max_capacity` The maximum capacity for this Baggage instance. |
| 69 | + Baggage(size_t max_capacity); |
| 70 | + |
| 71 | + /// Initializes a Baggage instance using the provided unordered_map of |
| 72 | + /// key-value pairs. The maximum capacity can also be specified. |
| 73 | + /// |
| 74 | + /// @param `baggage_map` The map containing key-value pairs to initialize the |
| 75 | + /// Baggage. |
| 76 | + /// @param `max_capacity` The maximum capacity for this Baggage instance. |
| 77 | + Baggage(std::unordered_map<std::string, std::string>, |
| 78 | + size_t max_capacity = default_max_capacity); |
| 79 | + |
| 80 | + /// Checks if the Baggage contains a specified key. |
| 81 | + /// |
| 82 | + /// @param `key` The key to check. |
| 83 | + /// @return `true` if the key exists in the Baggage; otherwise, `false`. |
| 84 | + bool contains(StringView key) const; |
| 85 | + |
| 86 | + /// Retrieves the value associated with a specified key. |
| 87 | + /// |
| 88 | + /// @param `key` The key to retrieve the value for. |
| 89 | + /// @return An `Optional<StringView>` containing the value if the key exists, |
| 90 | + /// or an empty Optional if the key is not found. |
| 91 | + Optional<StringView> get(StringView key) const; |
| 92 | + |
| 93 | + /// Adds a key-value pair to the Baggage. |
| 94 | + /// |
| 95 | + /// This function will attempt to add the given key-value pair to the Baggage. |
| 96 | + /// If the maximum capacity has been reached, the insertion will fail. |
| 97 | + /// If a `key` already exists, its value will be overwritten with `value`. |
| 98 | + /// |
| 99 | + /// @param `key` The key to insert. |
| 100 | + /// @param `value` The value to associate with the key. |
| 101 | + /// @return `true` if the key-value pair was successfully added; `false` if |
| 102 | + /// the maximum capacity was reached. |
| 103 | + bool set(std::string key, std::string value); |
| 104 | + |
| 105 | + /// Removes the key-value pair corresponding to the specified key. |
| 106 | + /// |
| 107 | + /// @param `key` The key to remove from the Baggage. |
| 108 | + void remove(StringView key); |
| 109 | + |
| 110 | + /// Removes all key-value pair. |
| 111 | + void clear(); |
| 112 | + |
| 113 | + /// Retrieves the number of items stored. |
| 114 | + size_t size() const; |
| 115 | + |
| 116 | + /// Returns whether any items are stored. |
| 117 | + bool empty() const; |
| 118 | + |
| 119 | + /// Visits each key-value pair in the Baggage and invoke the provided |
| 120 | + /// visitor function for each key-value pair in the Baggage. |
| 121 | + /// |
| 122 | + /// @param `visitor` A function object that will be called for each |
| 123 | + /// key-value pair. |
| 124 | + void visit(std::function<void(StringView, StringView)>&& visitor); |
| 125 | + |
| 126 | + /// Injects the Baggage data into a `DictWriter` with the constraint that |
| 127 | + /// the amount of bytes written does not exceed the specified maximum byte |
| 128 | + /// limit. |
| 129 | + /// |
| 130 | + /// @param `writer` The DictWriter to inject the data into. |
| 131 | + /// @param `opts` Injection options. |
| 132 | + /// @return An `Expected<void>`, which may either succeed or contain an |
| 133 | + /// error. |
| 134 | + Expected<void> inject(DictWriter& writer, |
| 135 | + const Options& opts = default_options) const; |
| 136 | + |
| 137 | + /// Equality operator for comparing two Baggage instances. |
| 138 | + inline bool operator==(const Baggage& rhs) const { |
| 139 | + return baggage_ == rhs.baggage_; |
| 140 | + } |
| 141 | + |
| 142 | + private: |
| 143 | + const size_t max_capacity_ = Baggage::default_max_capacity; |
| 144 | + std::unordered_map<std::string, std::string> baggage_; |
| 145 | +}; |
| 146 | + |
| 147 | +} // namespace tracing |
| 148 | +} // namespace datadog |
0 commit comments