load_reporter.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. #ifndef GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
  19. #define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
  20. #include <grpc/support/port_platform.h>
  21. #include <atomic>
  22. #include <chrono>
  23. #include <deque>
  24. #include <vector>
  25. #include <grpc/support/log.h>
  26. #include <grpcpp/impl/codegen/config.h>
  27. #include "src/cpp/server/load_reporter/load_data_store.h"
  28. #include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h"
  29. #include "opencensus/stats/stats.h"
  30. namespace grpc {
  31. namespace load_reporter {
  32. // The interface to get the Census stats. Abstracted for mocking.
  33. class CensusViewProvider {
  34. public:
  35. // Maps from the view name to the view data.
  36. using ViewDataMap =
  37. std::unordered_map<grpc::string, ::opencensus::stats::ViewData>;
  38. // Maps from the view name to the view descriptor.
  39. using ViewDescriptorMap =
  40. std::unordered_map<grpc::string, ::opencensus::stats::ViewDescriptor>;
  41. CensusViewProvider();
  42. virtual ~CensusViewProvider() = default;
  43. // Fetches the view data accumulated since last fetching, and returns it as a
  44. // map from the view name to the view data.
  45. virtual ViewDataMap FetchViewData() = 0;
  46. // A helper function that gets a row with the input tag values from the view
  47. // data. Only used when we know that row must exist because we have seen a row
  48. // with the same tag values in a related view data. Several ViewData's are
  49. // considered related if their views are based on the measures that are always
  50. // recorded at the same time.
  51. double static GetRelatedViewDataRowDouble(
  52. const ViewDataMap& view_data_map, const char* view_name,
  53. size_t view_name_len, const std::vector<grpc::string>& tag_values);
  54. protected:
  55. const ViewDescriptorMap& view_descriptor_map() const {
  56. return view_descriptor_map_;
  57. }
  58. private:
  59. ViewDescriptorMap view_descriptor_map_;
  60. // Tag keys.
  61. ::opencensus::stats::TagKey tag_key_token_;
  62. ::opencensus::stats::TagKey tag_key_host_;
  63. ::opencensus::stats::TagKey tag_key_user_id_;
  64. ::opencensus::stats::TagKey tag_key_status_;
  65. ::opencensus::stats::TagKey tag_key_metric_name_;
  66. };
  67. // The default implementation fetches the real stats from Census.
  68. class CensusViewProviderDefaultImpl : public CensusViewProvider {
  69. public:
  70. CensusViewProviderDefaultImpl();
  71. ViewDataMap FetchViewData() override;
  72. private:
  73. std::unordered_map<grpc::string, ::opencensus::stats::View> view_map_;
  74. };
  75. // The interface to get the CPU stats. Abstracted for mocking.
  76. class CpuStatsProvider {
  77. public:
  78. // The used and total amounts of CPU usage.
  79. using CpuStatsSample = std::pair<uint64_t, uint64_t>;
  80. virtual ~CpuStatsProvider() = default;
  81. // Gets the cumulative used CPU and total CPU resource.
  82. virtual CpuStatsSample GetCpuStats() = 0;
  83. };
  84. // The default implementation reads CPU jiffies from the system to calculate CPU
  85. // utilization.
  86. class CpuStatsProviderDefaultImpl : public CpuStatsProvider {
  87. public:
  88. CpuStatsSample GetCpuStats() override;
  89. };
  90. // Maintains all the load data and load reporting streams.
  91. class LoadReporter {
  92. public:
  93. // TODO(juanlishen): Allow config for providers from users.
  94. LoadReporter(uint32_t feedback_sample_window_seconds,
  95. std::unique_ptr<CensusViewProvider> census_view_provider,
  96. std::unique_ptr<CpuStatsProvider> cpu_stats_provider)
  97. : feedback_sample_window_seconds_(feedback_sample_window_seconds),
  98. census_view_provider_(std::move(census_view_provider)),
  99. cpu_stats_provider_(std::move(cpu_stats_provider)) {
  100. // Append the initial record so that the next real record can have a base.
  101. AppendNewFeedbackRecord(0, 0);
  102. }
  103. // Fetches the latest data from Census and merge it into the data store.
  104. // Also adds a new sample to the LB feedback sliding window.
  105. // Thread-unsafe. (1). The access to the load data store and feedback records
  106. // has locking. (2). The access to the Census view provider and CPU stats
  107. // provider lacks locking, but we only access these two members in this method
  108. // (in testing, we also access them when setting up expectation). So the
  109. // invocations of this method must be serialized.
  110. void FetchAndSample();
  111. // Generates a report for that host and balancer. The report contains
  112. // all the stats data accumulated between the last report (i.e., the last
  113. // consumption) and the last fetch from Census (i.e., the last production).
  114. // Thread-safe.
  115. ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> GenerateLoads(
  116. const grpc::string& hostname, const grpc::string& lb_id);
  117. // The feedback is calculated from the stats data recorded in the sliding
  118. // window. Outdated records are discarded.
  119. // Thread-safe.
  120. ::grpc::lb::v1::LoadBalancingFeedback GenerateLoadBalancingFeedback();
  121. // Wrapper around LoadDataStore::ReportStreamCreated.
  122. // Thread-safe.
  123. void ReportStreamCreated(const grpc::string& hostname,
  124. const grpc::string& lb_id,
  125. const grpc::string& load_key);
  126. // Wrapper around LoadDataStore::ReportStreamClosed.
  127. // Thread-safe.
  128. void ReportStreamClosed(const grpc::string& hostname,
  129. const grpc::string& lb_id);
  130. // Generates a unique LB ID of length kLbIdLength. Returns an empty string
  131. // upon failure. Thread-safe.
  132. grpc::string GenerateLbId();
  133. // Accessors only for testing.
  134. CensusViewProvider* census_view_provider() {
  135. return census_view_provider_.get();
  136. }
  137. CpuStatsProvider* cpu_stats_provider() { return cpu_stats_provider_.get(); }
  138. private:
  139. struct LoadBalancingFeedbackRecord {
  140. std::chrono::system_clock::time_point end_time;
  141. uint64_t rpcs;
  142. uint64_t errors;
  143. uint64_t cpu_usage;
  144. uint64_t cpu_limit;
  145. LoadBalancingFeedbackRecord(
  146. const std::chrono::system_clock::time_point& end_time, uint64_t rpcs,
  147. uint64_t errors, uint64_t cpu_usage, uint64_t cpu_limit)
  148. : end_time(end_time),
  149. rpcs(rpcs),
  150. errors(errors),
  151. cpu_usage(cpu_usage),
  152. cpu_limit(cpu_limit) {}
  153. };
  154. // Finds the view data about starting call from the view_data_map and merges
  155. // the data to the load data store.
  156. void ProcessViewDataCallStart(
  157. const CensusViewProvider::ViewDataMap& view_data_map);
  158. // Finds the view data about ending call from the view_data_map and merges the
  159. // data to the load data store.
  160. void ProcessViewDataCallEnd(
  161. const CensusViewProvider::ViewDataMap& view_data_map);
  162. // Finds the view data about the customized call metrics from the
  163. // view_data_map and merges the data to the load data store.
  164. void ProcessViewDataOtherCallMetrics(
  165. const CensusViewProvider::ViewDataMap& view_data_map);
  166. bool IsRecordInWindow(const LoadBalancingFeedbackRecord& record,
  167. std::chrono::system_clock::time_point now) {
  168. return record.end_time > now - feedback_sample_window_seconds_;
  169. }
  170. void AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors);
  171. // Extracts an OrphanedLoadIdentifier from the per-balancer store and attaches
  172. // it to the load.
  173. void AttachOrphanLoadId(::grpc::lb::v1::Load* load,
  174. const PerBalancerStore& per_balancer_store);
  175. std::atomic<int64_t> next_lb_id_{0};
  176. const std::chrono::seconds feedback_sample_window_seconds_;
  177. std::mutex feedback_mu_;
  178. std::deque<LoadBalancingFeedbackRecord> feedback_records_;
  179. // TODO(juanlishen): Lock in finer grain. Locking the whole store may be
  180. // too expensive.
  181. std::mutex store_mu_;
  182. LoadDataStore load_data_store_;
  183. std::unique_ptr<CensusViewProvider> census_view_provider_;
  184. std::unique_ptr<CpuStatsProvider> cpu_stats_provider_;
  185. };
  186. } // namespace load_reporter
  187. } // namespace grpc
  188. #endif // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H