Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/grpc/context_impl.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/grpc/context_impl.h"
2
3
#include <cstdint>
4
#include <memory>
5
#include <string>
6
#include <tuple>
7
#include <utility>
8
9
#include "source/common/grpc/common.h"
10
#include "source/common/stats/utility.h"
11
12
#include "absl/strings/str_replace.h"
13
14
namespace Envoy {
15
namespace Grpc {
16
17
ContextImpl::ContextImpl(Stats::SymbolTable& symbol_table)
18
    : stat_name_pool_(symbol_table), grpc_(stat_name_pool_.add("grpc")),
19
      grpc_web_(stat_name_pool_.add("grpc-web")), success_(stat_name_pool_.add("success")),
20
      failure_(stat_name_pool_.add("failure")), total_(stat_name_pool_.add("total")),
21
      zero_(stat_name_pool_.add("0")),
22
      request_message_count_(stat_name_pool_.add("request_message_count")),
23
      response_message_count_(stat_name_pool_.add("response_message_count")),
24
28.6k
      upstream_rq_time_(stat_name_pool_.add("upstream_rq_time")), stat_names_(symbol_table) {}
25
26
// Gets the stat prefix and underlying storage, depending on whether request_names is empty
27
Stats::ElementVec ContextImpl::statElements(Protocol protocol,
28
                                            const absl::optional<RequestStatNames>& request_names,
29
469
                                            Stats::Element suffix) {
30
469
  const Stats::StatName protocolName = protocolStatName(protocol);
31
469
  if (request_names) {
32
161
    return Stats::ElementVec{protocolName, request_names->service_, request_names->method_, suffix};
33
161
  }
34
308
  return Stats::ElementVec{protocolName, suffix};
35
469
}
36
37
void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol protocol,
38
                             const absl::optional<RequestStatNames>& request_names,
39
93
                             const Http::HeaderEntry* grpc_status) {
40
93
  if (!grpc_status) {
41
44
    return;
42
44
  }
43
44
49
  absl::string_view status_str = grpc_status->value().getStringView();
45
49
  auto iter = stat_names_.status_names_.find(status_str);
46
49
  Stats::ElementVec elements =
47
49
      statElements(protocol, request_names,
48
49
                   (iter != stat_names_.status_names_.end()) ? Stats::Element(iter->second)
49
49
                                                             : Stats::DynamicName(status_str));
50
49
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
51
49
  chargeStat(cluster, protocol, request_names, (status_str == "0"));
52
49
}
53
54
void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol protocol,
55
49
                             const absl::optional<RequestStatNames>& request_names, bool success) {
56
49
  Stats::ElementVec elements = statElements(protocol, request_names, successStatName(success));
57
49
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
58
49
  elements.back() = total_;
59
49
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
60
49
}
61
62
void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster,
63
0
                             const absl::optional<RequestStatNames>& request_names, bool success) {
64
0
  chargeStat(cluster, Protocol::Grpc, request_names, success);
65
0
}
66
67
void ContextImpl::chargeRequestMessageStat(const Upstream::ClusterInfo& cluster,
68
                                           const absl::optional<RequestStatNames>& request_names,
69
160
                                           uint64_t amount) {
70
160
  Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, request_message_count_);
71
160
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).add(amount);
72
160
}
73
74
void ContextImpl::chargeResponseMessageStat(const Upstream::ClusterInfo& cluster,
75
                                            const absl::optional<RequestStatNames>& request_names,
76
211
                                            uint64_t amount) {
77
211
  Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, response_message_count_);
78
211
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).add(amount);
79
211
}
80
81
void ContextImpl::chargeUpstreamStat(const Upstream::ClusterInfo& cluster,
82
                                     const absl::optional<RequestStatNames>& request_names,
83
0
                                     std::chrono::milliseconds duration) {
84
0
  Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, upstream_rq_time_);
85
0
  Stats::Utility::histogramFromElements(cluster.statsScope(), elements,
86
0
                                        Stats::Histogram::Unit::Milliseconds)
87
0
      .recordValue(duration.count());
88
0
}
89
90
absl::optional<ContextImpl::RequestStatNames>
91
29
ContextImpl::resolveDynamicServiceAndMethod(const Http::HeaderEntry* path) {
92
29
  absl::optional<Common::RequestNames> request_names = Common::resolveServiceAndMethod(path);
93
94
29
  if (!request_names) {
95
1
    return {};
96
1
  }
97
98
  // service/method will live until the request is finished to emit resulting stats (e.g. request
99
  // status) values in request_names_ might get changed, for example by routing rules (i.e.
100
  // "prefix_rewrite"), so we copy them here to preserve the initial value and get a proper stat
101
28
  Stats::Element service = Stats::DynamicSavedName(request_names->service_);
102
28
  Stats::Element method = Stats::DynamicSavedName(request_names->method_);
103
28
  return RequestStatNames{service, method};
104
29
}
105
106
absl::optional<ContextImpl::RequestStatNames>
107
8
ContextImpl::resolveDynamicServiceAndMethodWithDotReplaced(const Http::HeaderEntry* path) {
108
8
  absl::optional<Common::RequestNames> request_names = Common::resolveServiceAndMethod(path);
109
8
  if (!request_names) {
110
0
    return {};
111
0
  }
112
8
  Stats::Element service =
113
8
      Stats::DynamicSavedName(absl::StrReplaceAll(request_names->service_, {{".", "_"}}));
114
8
  Stats::Element method = Stats::DynamicSavedName(request_names->method_);
115
8
  return RequestStatNames{service, method};
116
8
}
117
118
} // namespace Grpc
119
} // namespace Envoy