Coverage Report

Created: 2024-09-19 09:45

/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
26.5k
      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
52
                                            Stats::Element suffix) {
30
52
  const Stats::StatName protocolName = protocolStatName(protocol);
31
52
  if (request_names) {
32
52
    return Stats::ElementVec{protocolName, request_names->service_, request_names->method_, suffix};
33
52
  }
34
0
  return Stats::ElementVec{protocolName, suffix};
35
52
}
36
37
void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol protocol,
38
                             const absl::optional<RequestStatNames>& request_names,
39
1
                             const Http::HeaderEntry* grpc_status) {
40
1
  if (!grpc_status) {
41
1
    return;
42
1
  }
43
44
0
  absl::string_view status_str = grpc_status->value().getStringView();
45
0
  auto iter = stat_names_.status_names_.find(status_str);
46
0
  Stats::ElementVec elements =
47
0
      statElements(protocol, request_names,
48
0
                   (iter != stat_names_.status_names_.end()) ? Stats::Element(iter->second)
49
0
                                                             : Stats::DynamicName(status_str));
50
0
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
51
0
  chargeStat(cluster, protocol, request_names, (status_str == "0"));
52
0
}
53
54
void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol protocol,
55
0
                             const absl::optional<RequestStatNames>& request_names, bool success) {
56
0
  Stats::ElementVec elements = statElements(protocol, request_names, successStatName(success));
57
0
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
58
0
  elements.back() = total_;
59
0
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
60
0
}
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
26
                                           uint64_t amount) {
70
26
  Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, request_message_count_);
71
26
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).add(amount);
72
26
}
73
74
void ContextImpl::chargeResponseMessageStat(const Upstream::ClusterInfo& cluster,
75
                                            const absl::optional<RequestStatNames>& request_names,
76
26
                                            uint64_t amount) {
77
26
  Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, response_message_count_);
78
26
  Stats::Utility::counterFromElements(cluster.statsScope(), elements).add(amount);
79
26
}
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
0
ContextImpl::resolveDynamicServiceAndMethod(const Http::HeaderEntry* path) {
92
0
  absl::optional<Common::RequestNames> request_names = Common::resolveServiceAndMethod(path);
93
94
0
  if (!request_names) {
95
0
    return {};
96
0
  }
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
0
  Stats::Element service = Stats::DynamicSavedName(request_names->service_);
102
0
  Stats::Element method = Stats::DynamicSavedName(request_names->method_);
103
0
  return RequestStatNames{service, method};
104
0
}
105
106
absl::optional<ContextImpl::RequestStatNames>
107
1
ContextImpl::resolveDynamicServiceAndMethodWithDotReplaced(const Http::HeaderEntry* path) {
108
1
  absl::optional<Common::RequestNames> request_names = Common::resolveServiceAndMethod(path);
109
1
  if (!request_names) {
110
0
    return {};
111
0
  }
112
1
  Stats::Element service =
113
1
      Stats::DynamicSavedName(absl::StrReplaceAll(request_names->service_, {{".", "_"}}));
114
1
  Stats::Element method = Stats::DynamicSavedName(request_names->method_);
115
1
  return RequestStatNames{service, method};
116
1
}
117
118
} // namespace Grpc
119
} // namespace Envoy