Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / src / core / ext / filters / client_channel / lb_policy / xds / xds_client_stats.cc
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h"
22
23 #include <grpc/support/atm.h>
24 #include <grpc/support/string_util.h>
25 #include <string.h>
26
27 namespace grpc_core {
28
29 namespace {
30
31 template <typename T>
32 T GetAndResetCounter(Atomic<T>* from) {
33   return from->Exchange(0, MemoryOrder::RELAXED);
34 }
35
36 }  // namespace
37
38 //
39 // XdsClientStats::LocalityStats::LoadMetric::Snapshot
40 //
41
42 bool XdsClientStats::LocalityStats::LoadMetric::Snapshot::IsAllZero() const {
43   return total_metric_value == 0 && num_requests_finished_with_metric == 0;
44 }
45
46 //
47 // XdsClientStats::LocalityStats::LoadMetric
48 //
49
50 XdsClientStats::LocalityStats::LoadMetric::Snapshot
51 XdsClientStats::LocalityStats::LoadMetric::GetSnapshotAndReset() {
52   Snapshot metric = {num_requests_finished_with_metric_, total_metric_value_};
53   num_requests_finished_with_metric_ = 0;
54   total_metric_value_ = 0;
55   return metric;
56 }
57
58 //
59 // XdsClientStats::LocalityStats::Snapshot
60 //
61
62 bool XdsClientStats::LocalityStats::Snapshot::IsAllZero() {
63   if (total_successful_requests != 0 || total_requests_in_progress != 0 ||
64       total_error_requests != 0 || total_issued_requests != 0) {
65     return false;
66   }
67   for (auto& p : load_metric_stats) {
68     const LoadMetric::Snapshot& metric_value = p.second;
69     if (!metric_value.IsAllZero()) return false;
70   }
71   return true;
72 }
73
74 //
75 // XdsClientStats::LocalityStats
76 //
77
78 XdsClientStats::LocalityStats::Snapshot
79 XdsClientStats::LocalityStats::GetSnapshotAndReset() {
80   Snapshot snapshot = {
81       GetAndResetCounter(&total_successful_requests_),
82       // Don't reset total_requests_in_progress because it's not
83       // related to a single reporting interval.
84       total_requests_in_progress_.Load(MemoryOrder::RELAXED),
85       GetAndResetCounter(&total_error_requests_),
86       GetAndResetCounter(&total_issued_requests_)};
87   {
88     MutexLock lock(&load_metric_stats_mu_);
89     for (auto& p : load_metric_stats_) {
90       const char* metric_name = p.first.get();
91       LoadMetric& metric_value = p.second;
92       snapshot.load_metric_stats.emplace(
93           UniquePtr<char>(gpr_strdup(metric_name)),
94           metric_value.GetSnapshotAndReset());
95     }
96   }
97   return snapshot;
98 }
99
100 void XdsClientStats::LocalityStats::AddCallStarted() {
101   total_issued_requests_.FetchAdd(1, MemoryOrder::RELAXED);
102   total_requests_in_progress_.FetchAdd(1, MemoryOrder::RELAXED);
103 }
104
105 void XdsClientStats::LocalityStats::AddCallFinished(bool fail) {
106   Atomic<uint64_t>& to_increment =
107       fail ? total_error_requests_ : total_successful_requests_;
108   to_increment.FetchAdd(1, MemoryOrder::RELAXED);
109   total_requests_in_progress_.FetchAdd(-1, MemoryOrder::ACQ_REL);
110 }
111
112 //
113 // XdsClientStats::Snapshot
114 //
115
116 bool XdsClientStats::Snapshot::IsAllZero() {
117   for (auto& p : upstream_locality_stats) {
118     if (!p.second.IsAllZero()) return false;
119   }
120   for (auto& p : dropped_requests) {
121     if (p.second != 0) return false;
122   }
123   return total_dropped_requests == 0;
124 }
125
126 //
127 // XdsClientStats
128 //
129
130 XdsClientStats::Snapshot XdsClientStats::GetSnapshotAndReset() {
131   grpc_millis now = ExecCtx::Get()->Now();
132   // Record total_dropped_requests and reporting interval in the snapshot.
133   Snapshot snapshot;
134   snapshot.total_dropped_requests =
135       GetAndResetCounter(&total_dropped_requests_);
136   snapshot.load_report_interval = now - last_report_time_;
137   // Update last report time.
138   last_report_time_ = now;
139   // Snapshot all the other stats.
140   for (auto& p : upstream_locality_stats_) {
141     snapshot.upstream_locality_stats.emplace(p.first,
142                                              p.second->GetSnapshotAndReset());
143   }
144   {
145     MutexLock lock(&dropped_requests_mu_);
146 #if GRPC_USE_CPP_STD_LIB
147     // This is a workaround for the case where some compilers cannot build
148     // move-assignment of map with non-copyable but movable key.
149     // https://stackoverflow.com/questions/36475497
150     std::swap(snapshot.dropped_requests, dropped_requests_);
151     dropped_requests_.clear();
152 #else
153     snapshot.dropped_requests = std::move(dropped_requests_);
154 #endif
155   }
156   return snapshot;
157 }
158
159 void XdsClientStats::MaybeInitLastReportTime() {
160   if (last_report_time_ == -1) last_report_time_ = ExecCtx::Get()->Now();
161 }
162
163 RefCountedPtr<XdsClientStats::LocalityStats> XdsClientStats::FindLocalityStats(
164     const RefCountedPtr<XdsLocalityName>& locality_name) {
165   auto iter = upstream_locality_stats_.find(locality_name);
166   if (iter == upstream_locality_stats_.end()) {
167     iter = upstream_locality_stats_
168                .emplace(locality_name, MakeRefCounted<LocalityStats>())
169                .first;
170   }
171   return iter->second;
172 }
173
174 void XdsClientStats::PruneLocalityStats() {
175   auto iter = upstream_locality_stats_.begin();
176   while (iter != upstream_locality_stats_.end()) {
177     if (iter->second->IsSafeToDelete()) {
178       iter = upstream_locality_stats_.erase(iter);
179     } else {
180       ++iter;
181     }
182   }
183 }
184
185 void XdsClientStats::AddCallDropped(const UniquePtr<char>& category) {
186   total_dropped_requests_.FetchAdd(1, MemoryOrder::RELAXED);
187   MutexLock lock(&dropped_requests_mu_);
188   auto iter = dropped_requests_.find(category);
189   if (iter == dropped_requests_.end()) {
190     dropped_requests_.emplace(UniquePtr<char>(gpr_strdup(category.get())), 1);
191   } else {
192     ++iter->second;
193   }
194 }
195
196 }  // namespace grpc_core