Coverage Report

Created: 2023-11-12 09:30

/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