Skip to content

Commit 465f12c

Browse files
authored
Provide stats for mixer client. (istio#315)
* Provide stats for mixer client. * Addressed some review comments. * Fix presubmit test failure. * Fix presubmit test failure.
1 parent 1fcab69 commit 465f12c

File tree

7 files changed

+165
-17
lines changed

7 files changed

+165
-17
lines changed

mixerclient/control/src/mock_mixer_client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class MockMixerClient : public ::istio::mixer_client::MixerClient {
3232
::istio::mixer_client::TransportCheckFunc transport,
3333
::istio::mixer_client::DoneFunc on_done));
3434
MOCK_METHOD1(Report, void(const ::istio::mixer::v1::Attributes& attributes));
35+
MOCK_CONST_METHOD1(GetStatistics,
36+
void(::istio::mixer_client::Statistics* stat));
3537
};
3638

3739
} // namespace mixer_control

mixerclient/include/client.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,28 @@ struct MixerClientOptions {
4848
Environment env;
4949
};
5050

51+
// The statistics recorded by mixerclient library.
52+
struct Statistics {
53+
// Total number of check calls.
54+
uint64_t total_check_calls;
55+
// Total number of remote check calls.
56+
uint64_t total_remote_check_calls;
57+
// Total number of remote check calls that blocking origin requests.
58+
uint64_t total_blocking_remote_check_calls;
59+
60+
// Total number of quota calls.
61+
uint64_t total_quota_calls;
62+
// Total number of remote quota calls.
63+
uint64_t total_remote_quota_calls;
64+
// Total number of remote quota calls that blocking origin requests.
65+
uint64_t total_blocking_remote_quota_calls;
66+
67+
// Total number of report calls.
68+
uint64_t total_report_calls;
69+
// Total number of remote report calls.
70+
uint64_t total_remote_report_calls;
71+
};
72+
5173
class MixerClient {
5274
public:
5375
// Destructor
@@ -69,6 +91,9 @@ class MixerClient {
6991

7092
// A report call.
7193
virtual void Report(const ::istio::mixer::v1::Attributes& attributes) = 0;
94+
95+
// Get statistics.
96+
virtual void GetStatistics(Statistics* stat) const = 0;
7297
};
7398

7499
// Creates a MixerClient object.

mixerclient/src/client_impl.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ MixerClientImpl::MixerClientImpl(const MixerClientOptions &options)
3939
if (options_.env.uuid_generate_func) {
4040
deduplication_id_base_ = options_.env.uuid_generate_func();
4141
}
42+
43+
total_check_calls_ = 0;
44+
total_remote_check_calls_ = 0;
45+
total_blocking_remote_check_calls_ = 0;
46+
total_quota_calls_ = 0;
47+
total_remote_quota_calls_ = 0;
48+
total_blocking_remote_quota_calls_ = 0;
4249
}
4350

4451
MixerClientImpl::~MixerClientImpl() {}
@@ -47,6 +54,8 @@ CancelFunc MixerClientImpl::Check(
4754
const Attributes &attributes,
4855
const std::vector<::istio::quota::Requirement> &quotas,
4956
TransportCheckFunc transport, DoneFunc on_done) {
57+
++total_check_calls_;
58+
5059
std::unique_ptr<CheckCache::CheckResult> check_result(
5160
new CheckCache::CheckResult);
5261
check_cache_->Check(attributes, check_result.get());
@@ -55,6 +64,9 @@ CancelFunc MixerClientImpl::Check(
5564
return nullptr;
5665
}
5766

67+
if (!quotas.empty()) {
68+
++total_quota_calls_;
69+
}
5870
std::unique_ptr<QuotaCache::CheckResult> quota_result(
5971
new QuotaCache::CheckResult);
6072
// Only use quota cache if Check is using cache with OK status.
@@ -87,6 +99,18 @@ CancelFunc MixerClientImpl::Check(
8799
if (!transport) {
88100
transport = options_.env.check_transport;
89101
}
102+
// We are going to make a remote call now.
103+
++total_remote_check_calls_;
104+
if (!quotas.empty()) {
105+
++total_remote_quota_calls_;
106+
}
107+
if (on_done) {
108+
++total_blocking_remote_check_calls_;
109+
if (!quotas.empty()) {
110+
++total_blocking_remote_quota_calls_;
111+
}
112+
}
113+
90114
return transport(
91115
request, response, [this, request_copy, response, raw_check_result,
92116
raw_quota_result, on_done](const Status &status) {
@@ -114,6 +138,17 @@ void MixerClientImpl::Report(const Attributes &attributes) {
114138
report_batch_->Report(attributes);
115139
}
116140

141+
void MixerClientImpl::GetStatistics(Statistics *stat) const {
142+
stat->total_check_calls = total_check_calls_;
143+
stat->total_remote_check_calls = total_remote_check_calls_;
144+
stat->total_blocking_remote_check_calls = total_blocking_remote_check_calls_;
145+
stat->total_quota_calls = total_quota_calls_;
146+
stat->total_remote_quota_calls = total_remote_quota_calls_;
147+
stat->total_blocking_remote_quota_calls = total_blocking_remote_quota_calls_;
148+
stat->total_report_calls = report_batch_->total_report_calls();
149+
stat->total_remote_report_calls = report_batch_->total_remote_report_calls();
150+
}
151+
117152
// Creates a MixerClient object.
118153
std::unique_ptr<MixerClient> CreateMixerClient(
119154
const MixerClientOptions &options) {

mixerclient/src/client_impl.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ class MixerClientImpl : public MixerClient {
3535
// Destructor
3636
virtual ~MixerClientImpl();
3737

38-
virtual CancelFunc Check(
39-
const ::istio::mixer::v1::Attributes& attributes,
40-
const std::vector<::istio::quota::Requirement>& quotas,
41-
TransportCheckFunc transport, DoneFunc on_done);
42-
virtual void Report(const ::istio::mixer::v1::Attributes& attributes);
38+
CancelFunc Check(const ::istio::mixer::v1::Attributes& attributes,
39+
const std::vector<::istio::quota::Requirement>& quotas,
40+
TransportCheckFunc transport, DoneFunc on_done) override;
41+
void Report(const ::istio::mixer::v1::Attributes& attributes) override;
42+
43+
void GetStatistics(Statistics* stat) const override;
4344

4445
private:
4546
// Store the options
@@ -59,6 +60,18 @@ class MixerClientImpl : public MixerClient {
5960
std::string deduplication_id_base_;
6061
std::atomic<std::uint64_t> deduplication_id_;
6162

63+
// Atomic objects for recording statistics.
64+
// check cache miss rate:
65+
// total_blocking_remote_check_calls_ / total_check_calls_.
66+
// quota cache miss rate:
67+
// total_blocking_remote_quota_calls_ / total_quota_calls_.
68+
std::atomic_int_fast64_t total_check_calls_;
69+
std::atomic_int_fast64_t total_remote_check_calls_;
70+
std::atomic_int_fast64_t total_blocking_remote_check_calls_;
71+
std::atomic_int_fast64_t total_quota_calls_;
72+
std::atomic_int_fast64_t total_remote_quota_calls_;
73+
std::atomic_int_fast64_t total_blocking_remote_quota_calls_;
74+
6275
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MixerClientImpl);
6376
};
6477

mixerclient/src/client_impl_test.cc

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,23 @@ TEST_F(MixerClientImplTest, TestSuccessCheck) {
8787
EXPECT_TRUE(done_status.ok());
8888

8989
for (int i = 0; i < 10; i++) {
90-
// Other calls should ba cached.
90+
// Other calls should be cached.
9191
Status done_status1 = Status::UNKNOWN;
9292
client_->Check(request_, empty_quotas, empty_transport_,
9393
[&done_status1](Status status) { done_status1 = status; });
9494
EXPECT_TRUE(done_status1.ok());
9595
}
96+
97+
Statistics stat;
98+
client_->GetStatistics(&stat);
99+
EXPECT_EQ(stat.total_check_calls, 11);
100+
// The first check call is a remote blocking check call.
101+
EXPECT_EQ(stat.total_remote_check_calls, 1);
102+
EXPECT_EQ(stat.total_blocking_remote_check_calls, 1);
103+
// Empty quota does not trigger any quota call.
104+
EXPECT_EQ(stat.total_quota_calls, 0);
105+
EXPECT_EQ(stat.total_remote_quota_calls, 0);
106+
EXPECT_EQ(stat.total_blocking_remote_quota_calls, 0);
96107
}
97108

98109
TEST_F(MixerClientImplTest, TestPerRequestTransport) {
@@ -116,12 +127,23 @@ TEST_F(MixerClientImplTest, TestPerRequestTransport) {
116127
EXPECT_TRUE(done_status.ok());
117128

118129
for (int i = 0; i < 10; i++) {
119-
// Other calls should ba cached.
130+
// Other calls should be cached.
120131
Status done_status1 = Status::UNKNOWN;
121132
client_->Check(request_, empty_quotas, local_check_transport.GetFunc(),
122133
[&done_status1](Status status) { done_status1 = status; });
123134
EXPECT_TRUE(done_status1.ok());
124135
}
136+
137+
Statistics stat;
138+
client_->GetStatistics(&stat);
139+
EXPECT_EQ(stat.total_check_calls, 11);
140+
// The first check call is a remote blocking check call.
141+
EXPECT_EQ(stat.total_remote_check_calls, 1);
142+
EXPECT_EQ(stat.total_blocking_remote_check_calls, 1);
143+
// Empty quota does not trigger any quota call.
144+
EXPECT_EQ(stat.total_quota_calls, 0);
145+
EXPECT_EQ(stat.total_remote_quota_calls, 0);
146+
EXPECT_EQ(stat.total_blocking_remote_quota_calls, 0);
125147
}
126148

127149
TEST_F(MixerClientImplTest, TestNoCheckCache) {
@@ -146,14 +168,23 @@ TEST_F(MixerClientImplTest, TestNoCheckCache) {
146168
EXPECT_TRUE(done_status.ok());
147169

148170
for (int i = 0; i < 10; i++) {
149-
// Other calls should ba cached.
171+
// Other calls are not cached.
150172
Status done_status1 = Status::UNKNOWN;
151173
client_->Check(request_, quotas_, empty_transport_,
152174
[&done_status1](Status status) { done_status1 = status; });
153175
EXPECT_TRUE(done_status1.ok());
154176
}
155177
// Call count 11 since check is not cached.
156-
EXPECT_LE(call_counts, 11);
178+
EXPECT_EQ(call_counts, 11);
179+
Statistics stat;
180+
client_->GetStatistics(&stat);
181+
// Because there is no check cache, we make remote blocking call every time.
182+
EXPECT_EQ(stat.total_check_calls, 11);
183+
EXPECT_EQ(stat.total_remote_check_calls, 11);
184+
EXPECT_EQ(stat.total_blocking_remote_check_calls, 11);
185+
EXPECT_EQ(stat.total_quota_calls, 11);
186+
EXPECT_EQ(stat.total_remote_quota_calls, 11);
187+
EXPECT_EQ(stat.total_blocking_remote_quota_calls, 11);
157188
}
158189

159190
TEST_F(MixerClientImplTest, TestNoQuotaCache) {
@@ -178,14 +209,23 @@ TEST_F(MixerClientImplTest, TestNoQuotaCache) {
178209
EXPECT_TRUE(done_status.ok());
179210

180211
for (int i = 0; i < 10; i++) {
181-
// Other calls should ba cached.
212+
// Other calls should be cached.
182213
Status done_status1 = Status::UNKNOWN;
183214
client_->Check(request_, quotas_, empty_transport_,
184215
[&done_status1](Status status) { done_status1 = status; });
185216
EXPECT_TRUE(done_status1.ok());
186217
}
187218
// Call count 11 since quota is not cached.
188-
EXPECT_LE(call_counts, 11);
219+
EXPECT_EQ(call_counts, 11);
220+
Statistics stat;
221+
client_->GetStatistics(&stat);
222+
// Because there is no quota cache, we make remote blocking call every time.
223+
EXPECT_EQ(stat.total_check_calls, 11);
224+
EXPECT_EQ(stat.total_remote_check_calls, 11);
225+
EXPECT_EQ(stat.total_blocking_remote_check_calls, 11);
226+
EXPECT_EQ(stat.total_quota_calls, 11);
227+
EXPECT_EQ(stat.total_remote_quota_calls, 11);
228+
EXPECT_EQ(stat.total_blocking_remote_quota_calls, 11);
189229
}
190230

191231
TEST_F(MixerClientImplTest, TestSuccessCheckAndQuota) {
@@ -208,14 +248,24 @@ TEST_F(MixerClientImplTest, TestSuccessCheckAndQuota) {
208248
EXPECT_TRUE(done_status.ok());
209249

210250
for (int i = 0; i < 10; i++) {
211-
// Other calls should ba cached.
251+
// Other calls should be cached.
212252
Status done_status1 = Status::UNKNOWN;
213253
client_->Check(request_, quotas_, empty_transport_,
214254
[&done_status1](Status status) { done_status1 = status; });
215255
EXPECT_TRUE(done_status1.ok());
216256
}
217257
// Call count should be less than 4
218258
EXPECT_LE(call_counts, 3);
259+
Statistics stat;
260+
client_->GetStatistics(&stat);
261+
// Less than 4 remote calls are made for prefetching, and they are
262+
// non-blocking remote calls.
263+
EXPECT_EQ(stat.total_check_calls, 11);
264+
EXPECT_LE(stat.total_remote_check_calls, 3);
265+
EXPECT_EQ(stat.total_blocking_remote_check_calls, 1);
266+
EXPECT_EQ(stat.total_quota_calls, 11);
267+
EXPECT_LE(stat.total_remote_quota_calls, 3);
268+
EXPECT_EQ(stat.total_blocking_remote_quota_calls, 1);
219269
}
220270

221271
TEST_F(MixerClientImplTest, TestFailedCheckAndQuota) {
@@ -238,12 +288,22 @@ TEST_F(MixerClientImplTest, TestFailedCheckAndQuota) {
238288
EXPECT_ERROR_CODE(Code::FAILED_PRECONDITION, done_status);
239289

240290
for (int i = 0; i < 10; i++) {
241-
// Other calls should ba cached.
291+
// Other calls should be cached.
242292
Status done_status1 = Status::UNKNOWN;
243293
client_->Check(request_, quotas_, empty_transport_,
244294
[&done_status1](Status status) { done_status1 = status; });
245295
EXPECT_ERROR_CODE(Code::FAILED_PRECONDITION, done_status1);
246296
}
297+
Statistics stat;
298+
client_->GetStatistics(&stat);
299+
// The first call is a remote blocking call, which returns failed precondition
300+
// in check response. Following calls only make check cache calls and return.
301+
EXPECT_EQ(stat.total_check_calls, 11);
302+
EXPECT_EQ(stat.total_remote_check_calls, 1);
303+
EXPECT_EQ(stat.total_blocking_remote_check_calls, 1);
304+
EXPECT_EQ(stat.total_quota_calls, 1);
305+
EXPECT_EQ(stat.total_remote_quota_calls, 1);
306+
EXPECT_EQ(stat.total_blocking_remote_quota_calls, 1);
247307
}
248308

249309
} // namespace

mixerclient/src/report_batch.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,15 @@ ReportBatch::ReportBatch(const ReportOptions& options,
3232
: options_(options),
3333
transport_(transport),
3434
timer_create_(timer_create),
35-
compressor_(compressor) {}
35+
compressor_(compressor),
36+
total_report_calls_(0),
37+
total_remote_report_calls_(0) {}
3638

3739
ReportBatch::~ReportBatch() { Flush(); }
3840

3941
void ReportBatch::Report(const Attributes& request) {
4042
std::lock_guard<std::mutex> lock(mutex_);
43+
++total_report_calls_;
4144
if (!batch_compressor_) {
4245
batch_compressor_ = compressor_.CreateBatchCompressor();
4346
}
@@ -66,6 +69,7 @@ void ReportBatch::FlushWithLock() {
6669
return;
6770
}
6871

72+
++total_remote_report_calls_;
6973
std::unique_ptr<ReportRequest> request = batch_compressor_->Finish();
7074
batch_compressor_.reset();
7175
if (timer_) {

mixerclient/src/report_batch.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
#ifndef MIXERCLIENT_REPORT_BATCH_H
1717
#define MIXERCLIENT_REPORT_BATCH_H
1818

19-
#include <mutex>
20-
2119
#include "include/client.h"
2220
#include "src/attribute_compressor.h"
2321

22+
#include <atomic>
23+
#include <mutex>
24+
2425
namespace istio {
2526
namespace mixer_client {
2627

@@ -32,12 +33,17 @@ class ReportBatch {
3233

3334
virtual ~ReportBatch();
3435

35-
// Make batched report call
36+
// Make batched report call.
3637
void Report(const ::istio::mixer::v1::Attributes& request);
3738

3839
// Flush out batched reports.
3940
void Flush();
4041

42+
uint64_t total_report_calls() const { return total_report_calls_; }
43+
uint64_t total_remote_report_calls() const {
44+
return total_remote_report_calls_;
45+
}
46+
4147
private:
4248
void FlushWithLock();
4349

@@ -62,6 +68,9 @@ class ReportBatch {
6268
// batched report compressor
6369
std::unique_ptr<BatchCompressor> batch_compressor_;
6470

71+
std::atomic_int_fast64_t total_report_calls_;
72+
std::atomic_int_fast64_t total_remote_report_calls_;
73+
6574
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReportBatch);
6675
};
6776

0 commit comments

Comments
 (0)