/proc/self/cwd/source/common/http/codes.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <chrono> |
4 | | #include <cstdint> |
5 | | #include <string> |
6 | | |
7 | | #include "envoy/http/codes.h" |
8 | | #include "envoy/http/header_map.h" |
9 | | #include "envoy/stats/scope.h" |
10 | | |
11 | | #include "source/common/common/thread.h" |
12 | | #include "source/common/stats/symbol_table.h" |
13 | | |
14 | | namespace Envoy { |
15 | | namespace Http { |
16 | | |
17 | | struct CodeStats::ResponseStatInfo { |
18 | | Stats::Scope& global_scope_; |
19 | | Stats::Scope& cluster_scope_; |
20 | | Stats::StatName prefix_; |
21 | | uint64_t response_status_code_; |
22 | | bool internal_request_; |
23 | | Stats::StatName request_vhost_name_; |
24 | | Stats::StatName request_vcluster_name_; |
25 | | Stats::StatName request_route_name_; |
26 | | Stats::StatName from_zone_; |
27 | | Stats::StatName to_zone_; |
28 | | bool upstream_canary_; |
29 | | }; |
30 | | |
31 | | struct CodeStats::ResponseTimingInfo { |
32 | | Stats::Scope& global_scope_; |
33 | | Stats::Scope& cluster_scope_; |
34 | | Stats::StatName prefix_; |
35 | | std::chrono::milliseconds response_time_; |
36 | | bool upstream_canary_; |
37 | | bool internal_request_; |
38 | | Stats::StatName request_vhost_name_; |
39 | | Stats::StatName request_vcluster_name_; |
40 | | Stats::StatName request_route_name_; |
41 | | Stats::StatName from_zone_; |
42 | | Stats::StatName to_zone_; |
43 | | }; |
44 | | |
45 | | class CodeStatsImpl : public CodeStats { |
46 | | public: |
47 | | explicit CodeStatsImpl(Stats::SymbolTable& symbol_table); |
48 | | |
49 | | // CodeStats |
50 | | void chargeBasicResponseStat(Stats::Scope& scope, Stats::StatName prefix, Code response_code, |
51 | | bool exclude_http_code_stats) const override; |
52 | | void chargeResponseStat(const ResponseStatInfo& info, |
53 | | bool exclude_http_code_stats) const override; |
54 | | void chargeResponseTiming(const ResponseTimingInfo& info) const override; |
55 | | |
56 | | private: |
57 | | friend class CodeStatsTest; |
58 | | |
59 | | void writeCategory(const ResponseStatInfo& info, Stats::StatName rq_group, |
60 | | Stats::StatName rq_code, Stats::StatName category) const; |
61 | | void incCounter(Stats::Scope& scope, const Stats::StatNameVec& names) const; |
62 | | void incCounter(Stats::Scope& scope, Stats::StatName a, Stats::StatName b) const; |
63 | | void recordHistogram(Stats::Scope& scope, const Stats::StatNameVec& names, |
64 | | Stats::Histogram::Unit unit, uint64_t count) const; |
65 | | |
66 | | Stats::StatName upstreamRqGroup(Code response_code) const; |
67 | | Stats::StatName upstreamRqStatName(Code response_code) const; |
68 | | |
69 | | mutable Stats::StatNamePool stat_name_pool_; |
70 | | Stats::SymbolTable& symbol_table_; |
71 | | |
72 | | const Stats::StatName canary_; |
73 | | const Stats::StatName empty_; // Used for the group-name for invalid http codes. |
74 | | const Stats::StatName external_; |
75 | | const Stats::StatName internal_; |
76 | | const Stats::StatName upstream_; |
77 | | const Stats::StatName upstream_rq_1xx_; |
78 | | const Stats::StatName upstream_rq_2xx_; |
79 | | const Stats::StatName upstream_rq_3xx_; |
80 | | const Stats::StatName upstream_rq_4xx_; |
81 | | const Stats::StatName upstream_rq_5xx_; |
82 | | const Stats::StatName upstream_rq_unknown_; |
83 | | const Stats::StatName upstream_rq_completed_; |
84 | | const Stats::StatName upstream_rq_time_; |
85 | | const Stats::StatName vcluster_; |
86 | | const Stats::StatName vhost_; |
87 | | const Stats::StatName route_; |
88 | | const Stats::StatName zone_; |
89 | | |
90 | | // Use an array of atomic pointers to hold StatNameStorage objects for |
91 | | // every conceivable HTTP response code. In the hot-path we'll reference |
92 | | // these with a null-check, and if we need to allocate a symbol for a |
93 | | // new code, we'll take a mutex to avoid duplicate allocations and |
94 | | // subsequent leaks. This is similar in principle to a ReaderMutexLock, |
95 | | // but should be faster, as ReaderMutexLocks appear to be too expensive for |
96 | | // fine-grained controls. Another option would be to use a lock per |
97 | | // stat-name, which might have similar performance to atomics with default |
98 | | // barrier policy. |
99 | | // |
100 | | // We don't allocate these all up front during construction because |
101 | | // SymbolTable greedily encodes the first 128 names it discovers in one |
102 | | // byte. We don't want those high-value single-byte codes to go to fully |
103 | | // enumerating the 4 prefixes combined with HTTP codes that are seldom used, |
104 | | // so we allocate these on demand. |
105 | | // |
106 | | // There can be multiple symbol tables in a server. The one passed into the |
107 | | // Codes constructor should be the same as the one passed to |
108 | | // Stats::ThreadLocalStore. Note that additional symbol tables can be created |
109 | | // from IsolatedStoreImpl's default constructor. |
110 | | // |
111 | | // The Codes object is global to the server. |
112 | | |
113 | | static constexpr uint32_t NumHttpCodes = 500; |
114 | | static constexpr uint32_t HttpCodeOffset = 100; // code 100 is at index 0. |
115 | | mutable Thread::AtomicPtrArray<const uint8_t, NumHttpCodes, |
116 | | Thread::AtomicPtrAllocMode::DoNotDelete> |
117 | | rc_stat_names_; |
118 | | }; |
119 | | |
120 | | /** |
121 | | * General utility routines for HTTP codes. |
122 | | */ |
123 | | class CodeUtility { |
124 | | public: |
125 | | /** |
126 | | * Convert an HTTP response code to a descriptive string. |
127 | | * @param code supplies the code to convert. |
128 | | * @return const char* the string. |
129 | | */ |
130 | | static const char* toString(Code code); |
131 | | |
132 | 260k | static bool is1xx(uint64_t code) { return code >= 100 && code < 200; } |
133 | 115k | static bool is2xx(uint64_t code) { return code >= 200 && code < 300; } |
134 | 111k | static bool is3xx(uint64_t code) { return code >= 300 && code < 400; } |
135 | 111k | static bool is4xx(uint64_t code) { return code >= 400 && code < 500; } |
136 | 4.99k | static bool is5xx(uint64_t code) { return code >= 500 && code < 600; } |
137 | | |
138 | 0 | static bool isGatewayError(uint64_t code) { return code >= 502 && code < 505; } |
139 | | |
140 | | static std::string groupStringForResponseCode(Code response_code); |
141 | | }; |
142 | | |
143 | | } // namespace Http |
144 | | } // namespace Envoy |