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(Atomic<uint64_t> * from)34 uint64_t GetAndResetCounter(Atomic<uint64_t>* from) {
35   return from->Exchange(0, MemoryOrder::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_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_.FetchAdd(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_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 = {GetAndResetCounter(&total_successful_requests_),
136                        // Don't reset total_requests_in_progress because it's
137                        // not related to a single reporting interval.
138                        total_requests_in_progress_.Load(MemoryOrder::RELAXED),
139                        GetAndResetCounter(&total_error_requests_),
140                        GetAndResetCounter(&total_issued_requests_)};
141   MutexLock lock(&backend_metrics_mu_);
142   snapshot.backend_metrics = std::move(backend_metrics_);
143   return snapshot;
144 }
145 
AddCallStarted()146 void XdsClusterLocalityStats::AddCallStarted() {
147   total_issued_requests_.FetchAdd(1, MemoryOrder::RELAXED);
148   total_requests_in_progress_.FetchAdd(1, MemoryOrder::RELAXED);
149 }
150 
AddCallFinished(bool fail)151 void XdsClusterLocalityStats::AddCallFinished(bool fail) {
152   Atomic<uint64_t>& to_increment =
153       fail ? total_error_requests_ : total_successful_requests_;
154   to_increment.FetchAdd(1, MemoryOrder::RELAXED);
155   total_requests_in_progress_.FetchAdd(-1, MemoryOrder::ACQ_REL);
156 }
157 
158 }  // namespace grpc_core
159