Line data Source code
1 : #pragma once 2 : 3 : #include <functional> 4 : #include <string> 5 : #include <vector> 6 : 7 : #include "envoy/common/time.h" 8 : 9 : #include "source/common/common/logger.h" 10 : #include "source/common/common/random_generator.h" 11 : #include "source/extensions/tracers/xray/reservoir.h" 12 : #include "source/extensions/tracers/xray/sampling_strategy.h" 13 : 14 : #include "absl/strings/string_view.h" 15 : 16 : namespace Envoy { 17 : namespace Extensions { 18 : namespace Tracers { 19 : namespace XRay { 20 : 21 : /** 22 : * This class encompasses the algorithm used when deciding whether to sample a given request. 23 : * The rule contains wildcard strings for matching a request based on its hostname, HTTP method or 24 : * URL path. A request must match on all 3 parts before this rule is applied. 25 : * If the rule applies, then |fixed_target| determines how many requests to sample per second. 26 : * While, rate determines the percentage of requests to sample after that within the same second. 27 : * 28 : * By default, this tracer records the first request each second, and five percent of 29 : * any additional requests. 30 : */ 31 : class LocalizedSamplingRule { 32 : public: 33 : /** 34 : * Creates a default sampling rule that has the default |fixed_target| and default |rate| set. 35 : */ 36 : static LocalizedSamplingRule createDefault(); 37 : 38 : LocalizedSamplingRule(uint32_t fixed_target, double rate) 39 0 : : fixed_target_(fixed_target), rate_(rate), reservoir_(fixed_target_) {} 40 : 41 : /** 42 : * Determines whether Hostname, HTTP method and URL path match the given request. 43 : */ 44 : bool appliesTo(const SamplingRequest& request) const; 45 : 46 : /** 47 : * Set the hostname to match against. 48 : * This value can contain wildcard characters such as '*' or '?'. 49 : */ 50 0 : void setHost(absl::string_view host) { host_ = std::string(host); } 51 : 52 : /** 53 : * Set the HTTP method to match against. 54 : * This value can contain wildcard characters such as '*' or '?'. 55 : */ 56 0 : void setHttpMethod(absl::string_view http_method) { http_method_ = std::string(http_method); } 57 : 58 : /** 59 : * Set the URL path to match against. 60 : * This value can contain wildcard characters such as '*' or '?'. 61 : */ 62 0 : void setUrlPath(absl::string_view url_path) { url_path_ = std::string(url_path); } 63 : 64 : /** 65 : * Set the minimum number of requests to sample per second. 66 : */ 67 0 : void setFixedTarget(uint32_t fixed_target) { 68 0 : fixed_target_ = fixed_target; 69 0 : reservoir_ = Reservoir(fixed_target); 70 0 : } 71 : 72 : /** 73 : * Set the percentage of requests to sample _after_ sampling |fixed_target| requests per second. 74 : */ 75 0 : void setRate(double rate) { rate_ = rate; } 76 0 : double rate() const { return rate_; } 77 0 : Reservoir& reservoir() { return reservoir_; } 78 : 79 : private: 80 : std::string host_; 81 : std::string http_method_; 82 : std::string url_path_; 83 : uint32_t fixed_target_; 84 : double rate_; 85 : Reservoir reservoir_; 86 : }; 87 : 88 : /** 89 : * The manifest represents the set of sampling rules (custom and default) used to match incoming 90 : * requests. 91 : */ 92 : class LocalizedSamplingManifest { 93 : public: 94 : /** 95 : * Create a default manifest. The default manifest is used when a custom manifest does not exist 96 : * or failed to parse. The default manifest, will have an empty set of custom rules. 97 : */ 98 0 : static LocalizedSamplingManifest createDefault() { 99 0 : return LocalizedSamplingManifest{LocalizedSamplingRule::createDefault()}; 100 0 : } 101 : 102 : /** 103 : * Create a manifest by de-serializing the input string as JSON representation of the sampling 104 : * rules. 105 : * @param sampling_rules_json JSON representation of X-Ray localized sampling rules. 106 : */ 107 : explicit LocalizedSamplingManifest(const std::string& sampling_rules_json); 108 : 109 : /** 110 : * Create a manifest by assigning the argument rule as the default rule. The set of custom rules 111 : * in this manifest will be empty. 112 : * @param default_rule A localized sampling rule that will be assigned as the default rule. 113 : */ 114 : explicit LocalizedSamplingManifest(const LocalizedSamplingRule& default_rule) 115 0 : : default_rule_(default_rule) {} 116 : 117 : /** 118 : * @return default sampling rule 119 : */ 120 0 : LocalizedSamplingRule& defaultRule() { return default_rule_; } 121 : 122 : /** 123 : * @return the user-defined sampling rules 124 : */ 125 0 : std::vector<LocalizedSamplingRule>& customRules() { return custom_rules_; } 126 : 127 : /** 128 : * @return true if this manifest has a set of custom rules; otherwise false. 129 : */ 130 0 : bool hasCustomRules() const { return !custom_rules_.empty(); } 131 : 132 : private: 133 : LocalizedSamplingRule default_rule_; 134 : std::vector<LocalizedSamplingRule> custom_rules_; 135 : }; 136 : 137 : class LocalizedSamplingStrategy : public SamplingStrategy { 138 : public: 139 : LocalizedSamplingStrategy(const std::string& sampling_rules_json, Random::RandomGenerator& rng, 140 : TimeSource& time_source) 141 0 : : SamplingStrategy(rng), manifest_(sampling_rules_json), time_source_(time_source) {} 142 : 143 : /** 144 : * Determines if an incoming request matches one of the sampling rules in the local manifest. 145 : * If a match is found, then the request might be traced based on the sampling percentages etc. 146 : * determined by the matching rule. 147 : */ 148 : bool shouldTrace(const SamplingRequest& sampling_request) override; 149 : 150 0 : const LocalizedSamplingManifest manifest() const { return manifest_; } 151 : 152 : private: 153 : bool shouldTrace(LocalizedSamplingRule& rule); 154 : LocalizedSamplingManifest manifest_; 155 : TimeSource& time_source_; 156 : }; 157 : 158 : } // namespace XRay 159 : } // namespace Tracers 160 : } // namespace Extensions 161 : } // namespace Envoy