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