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/xds/xds_client_stats.h"
22 
23 #include <string.h>
24 
25 #include <grpc/support/atm.h>
26 #include <grpc/support/string_util.h>
27 
28 #include "src/core/ext/xds/xds_client.h"
29 
30 namespace grpc_core {
31 
32 namespace {
33 
GetAndResetCounter(std::atomic<uint64_t> * from)34 uint64_t GetAndResetCounter(std::atomic<uint64_t>* from) {
35   return from->exchange(0, std::memory_order_relaxed);
36 }
37 
38 }  // namespace
39 
40 //
41 // XdsClusterDropStats
42 //
43 
XdsClusterDropStats(RefCountedPtr<XdsClient> xds_client,absl::string_view lrs_server_name,absl::string_view cluster_name,absl::string_view eds_service_name)44 XdsClusterDropStats::XdsClusterDropStats(RefCountedPtr<XdsClient> xds_client,
45                                          absl::string_view lrs_server_name,
46                                          absl::string_view cluster_name,
47                                          absl::string_view eds_service_name)
48     : RefCounted(GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_refcount_trace)
49                      ? "XdsClusterDropStats"
50                      : nullptr),
51       xds_client_(std::move(xds_client)),
52       lrs_server_name_(lrs_server_name),
53       cluster_name_(cluster_name),
54       eds_service_name_(eds_service_name) {
55   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
56     gpr_log(GPR_INFO, "[xds_client %p] created drop stats %p for {%s, %s, %s}",
57             xds_client_.get(), this, std::string(lrs_server_name_).c_str(),
58             std::string(cluster_name_).c_str(),
59             std::string(eds_service_name_).c_str());
60   }
61 }
62 
~XdsClusterDropStats()63 XdsClusterDropStats::~XdsClusterDropStats() {
64   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
65     gpr_log(GPR_INFO,
66             "[xds_client %p] destroying drop stats %p for {%s, %s, %s}",
67             xds_client_.get(), this, std::string(lrs_server_name_).c_str(),
68             std::string(cluster_name_).c_str(),
69             std::string(eds_service_name_).c_str());
70   }
71   xds_client_->RemoveClusterDropStats(lrs_server_name_, cluster_name_,
72                                       eds_service_name_, this);
73   xds_client_.reset(DEBUG_LOCATION, "DropStats");
74 }
75 
GetSnapshotAndReset()76 XdsClusterDropStats::Snapshot XdsClusterDropStats::GetSnapshotAndReset() {
77   Snapshot snapshot;
78   snapshot.uncategorized_drops = GetAndResetCounter(&uncategorized_drops_);
79   MutexLock lock(&mu_);
80   snapshot.categorized_drops = std::move(categorized_drops_);
81   return snapshot;
82 }
83 
AddUncategorizedDrops()84 void XdsClusterDropStats::AddUncategorizedDrops() {
85   uncategorized_drops_.fetch_add(1);
86 }
87 
AddCallDropped(const std::string & category)88 void XdsClusterDropStats::AddCallDropped(const std::string& category) {
89   MutexLock lock(&mu_);
90   ++categorized_drops_[category];
91 }
92 
93 //
94 // XdsClusterLocalityStats
95 //
96 
XdsClusterLocalityStats(RefCountedPtr<XdsClient> xds_client,absl::string_view lrs_server_name,absl::string_view cluster_name,absl::string_view eds_service_name,RefCountedPtr<XdsLocalityName> name)97 XdsClusterLocalityStats::XdsClusterLocalityStats(
98     RefCountedPtr<XdsClient> xds_client, absl::string_view lrs_server_name,
99     absl::string_view cluster_name, absl::string_view eds_service_name,
100     RefCountedPtr<XdsLocalityName> name)
101     : RefCounted(GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_refcount_trace)
102                      ? "XdsClusterLocalityStats"
103                      : nullptr),
104       xds_client_(std::move(xds_client)),
105       lrs_server_name_(lrs_server_name),
106       cluster_name_(cluster_name),
107       eds_service_name_(eds_service_name),
108       name_(std::move(name)) {
109   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
110     gpr_log(GPR_INFO,
111             "[xds_client %p] created locality stats %p for {%s, %s, %s, %s}",
112             xds_client_.get(), this, std::string(lrs_server_name_).c_str(),
113             std::string(cluster_name_).c_str(),
114             std::string(eds_service_name_).c_str(),
115             name_->AsHumanReadableString().c_str());
116   }
117 }
118 
~XdsClusterLocalityStats()119 XdsClusterLocalityStats::~XdsClusterLocalityStats() {
120   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
121     gpr_log(GPR_INFO,
122             "[xds_client %p] destroying locality stats %p for {%s, %s, %s, %s}",
123             xds_client_.get(), this, std::string(lrs_server_name_).c_str(),
124             std::string(cluster_name_).c_str(),
125             std::string(eds_service_name_).c_str(),
126             name_->AsHumanReadableString().c_str());
127   }
128   xds_client_->RemoveClusterLocalityStats(lrs_server_name_, cluster_name_,
129                                           eds_service_name_, name_, this);
130   xds_client_.reset(DEBUG_LOCATION, "LocalityStats");
131 }
132 
133 XdsClusterLocalityStats::Snapshot
GetSnapshotAndReset()134 XdsClusterLocalityStats::GetSnapshotAndReset() {
135   Snapshot snapshot = {
136       GetAndResetCounter(&total_successful_requests_),
137       // Don't reset total_requests_in_progress because it's
138       // not related to a single reporting interval.
139       total_requests_in_progress_.load(std::memory_order_relaxed),
140       GetAndResetCounter(&total_error_requests_),
141       GetAndResetCounter(&total_issued_requests_),
142       {}};
143   MutexLock lock(&backend_metrics_mu_);
144   snapshot.backend_metrics = std::move(backend_metrics_);
145   return snapshot;
146 }
147 
AddCallStarted()148 void XdsClusterLocalityStats::AddCallStarted() {
149   total_issued_requests_.fetch_add(1, std::memory_order_relaxed);
150   total_requests_in_progress_.fetch_add(1, std::memory_order_relaxed);
151 }
152 
AddCallFinished(bool fail)153 void XdsClusterLocalityStats::AddCallFinished(bool fail) {
154   std::atomic<uint64_t>& to_increment =
155       fail ? total_error_requests_ : total_successful_requests_;
156   to_increment.fetch_add(1, std::memory_order_relaxed);
157   total_requests_in_progress_.fetch_add(-1, std::memory_order_acq_rel);
158 }
159 
160 }  // namespace grpc_core
161