couchbase 3.1.1-universal-darwin-20 → 3.2.0-universal-darwin-20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +3 -1
  4. data/ext/build_version.hxx.in +1 -1
  5. data/ext/cmake/Testing.cmake +1 -0
  6. data/ext/cmake/ThirdPartyDependencies.cmake +6 -0
  7. data/ext/cmake/VersionInfo.cmake +3 -0
  8. data/ext/couchbase/bucket.hxx +47 -28
  9. data/ext/couchbase/cbsasl/client.h +1 -1
  10. data/ext/couchbase/cbsasl/context.cc +1 -1
  11. data/ext/couchbase/cbsasl/context.h +3 -3
  12. data/ext/couchbase/cbsasl/mechanism.cc +5 -8
  13. data/ext/couchbase/cbsasl/mechanism.h +1 -4
  14. data/ext/couchbase/cbsasl/plain/plain.cc +1 -1
  15. data/ext/couchbase/cbsasl/scram-sha/scram-sha.cc +30 -36
  16. data/ext/couchbase/cluster.hxx +40 -22
  17. data/ext/couchbase/cluster_options.hxx +7 -1
  18. data/ext/couchbase/configuration.hxx +37 -16
  19. data/ext/couchbase/couchbase.cxx +1145 -291
  20. data/ext/couchbase/error_map.hxx +1 -1
  21. data/ext/couchbase/errors.hxx +25 -17
  22. data/ext/couchbase/io/dns_client.hxx +3 -3
  23. data/ext/couchbase/io/dns_codec.hxx +4 -5
  24. data/ext/couchbase/io/dns_config.hxx +5 -6
  25. data/ext/couchbase/io/dns_message.hxx +3 -3
  26. data/ext/couchbase/io/http_command.hxx +70 -35
  27. data/ext/couchbase/io/http_session.hxx +4 -3
  28. data/ext/couchbase/io/http_session_manager.hxx +28 -19
  29. data/ext/couchbase/io/mcbp_command.hxx +51 -19
  30. data/ext/couchbase/io/mcbp_context.hxx +1 -1
  31. data/ext/couchbase/io/mcbp_parser.hxx +4 -4
  32. data/ext/couchbase/io/mcbp_session.hxx +91 -101
  33. data/ext/couchbase/io/query_cache.hxx +2 -2
  34. data/ext/couchbase/io/retry_orchestrator.hxx +2 -4
  35. data/ext/couchbase/io/retry_reason.hxx +2 -2
  36. data/ext/couchbase/io/retry_strategy.hxx +1 -6
  37. data/ext/couchbase/io/streams.hxx +7 -7
  38. data/ext/couchbase/metrics/logging_meter.hxx +228 -0
  39. data/ext/couchbase/metrics/logging_meter_options.hxx +28 -0
  40. data/ext/couchbase/metrics/meter.hxx +49 -0
  41. data/ext/couchbase/metrics/noop_meter.hxx +43 -0
  42. data/ext/couchbase/operations.hxx +4 -0
  43. data/ext/couchbase/operations/analytics_dataset_create.hxx +16 -12
  44. data/ext/couchbase/operations/analytics_dataset_drop.hxx +11 -11
  45. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +6 -6
  46. data/ext/couchbase/operations/analytics_dataverse_create.hxx +10 -11
  47. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +10 -11
  48. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +9 -11
  49. data/ext/couchbase/operations/analytics_index_create.hxx +14 -13
  50. data/ext/couchbase/operations/analytics_index_drop.hxx +18 -12
  51. data/ext/couchbase/operations/analytics_index_get_all.hxx +8 -6
  52. data/ext/couchbase/operations/analytics_link.hxx +39 -0
  53. data/ext/couchbase/operations/analytics_link_azure_blob_external.hxx +145 -0
  54. data/ext/couchbase/operations/analytics_link_connect.hxx +14 -12
  55. data/ext/couchbase/operations/analytics_link_couchbase_remote.hxx +220 -0
  56. data/ext/couchbase/operations/analytics_link_create.hxx +128 -0
  57. data/ext/couchbase/operations/analytics_link_disconnect.hxx +11 -12
  58. data/ext/couchbase/operations/analytics_link_drop.hxx +130 -0
  59. data/ext/couchbase/operations/analytics_link_get_all.hxx +160 -0
  60. data/ext/couchbase/operations/analytics_link_replace.hxx +128 -0
  61. data/ext/couchbase/operations/analytics_link_s3_external.hxx +122 -0
  62. data/ext/couchbase/operations/bucket_create.hxx +8 -8
  63. data/ext/couchbase/operations/bucket_drop.hxx +5 -5
  64. data/ext/couchbase/operations/bucket_flush.hxx +5 -5
  65. data/ext/couchbase/operations/bucket_get.hxx +7 -7
  66. data/ext/couchbase/operations/bucket_get_all.hxx +7 -5
  67. data/ext/couchbase/operations/bucket_settings.hxx +40 -49
  68. data/ext/couchbase/operations/bucket_update.hxx +8 -8
  69. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +7 -7
  70. data/ext/couchbase/operations/collection_create.hxx +11 -11
  71. data/ext/couchbase/operations/collection_drop.hxx +12 -10
  72. data/ext/couchbase/operations/collections_manifest_get.hxx +3 -3
  73. data/ext/couchbase/operations/design_document.hxx +2 -2
  74. data/ext/couchbase/operations/document_analytics.hxx +29 -36
  75. data/ext/couchbase/operations/document_append.hxx +3 -3
  76. data/ext/couchbase/operations/document_decrement.hxx +3 -3
  77. data/ext/couchbase/operations/document_exists.hxx +2 -2
  78. data/ext/couchbase/operations/document_get.hxx +3 -3
  79. data/ext/couchbase/operations/document_get_and_lock.hxx +5 -3
  80. data/ext/couchbase/operations/document_get_and_touch.hxx +5 -3
  81. data/ext/couchbase/operations/document_get_projected.hxx +10 -11
  82. data/ext/couchbase/operations/document_increment.hxx +3 -3
  83. data/ext/couchbase/operations/document_insert.hxx +3 -3
  84. data/ext/couchbase/operations/document_lookup_in.hxx +12 -18
  85. data/ext/couchbase/operations/document_mutate_in.hxx +13 -18
  86. data/ext/couchbase/operations/document_prepend.hxx +3 -3
  87. data/ext/couchbase/operations/document_query.hxx +39 -41
  88. data/ext/couchbase/operations/document_remove.hxx +3 -3
  89. data/ext/couchbase/operations/document_replace.hxx +3 -3
  90. data/ext/couchbase/operations/document_search.hxx +56 -61
  91. data/ext/couchbase/operations/document_touch.hxx +3 -3
  92. data/ext/couchbase/operations/document_unlock.hxx +3 -3
  93. data/ext/couchbase/operations/document_upsert.hxx +3 -3
  94. data/ext/couchbase/operations/document_view.hxx +23 -23
  95. data/ext/couchbase/operations/group_drop.hxx +5 -5
  96. data/ext/couchbase/operations/group_get.hxx +7 -7
  97. data/ext/couchbase/operations/group_get_all.hxx +6 -6
  98. data/ext/couchbase/operations/group_upsert.hxx +11 -11
  99. data/ext/couchbase/operations/http_noop.hxx +6 -6
  100. data/ext/couchbase/operations/mcbp_noop.hxx +3 -3
  101. data/ext/couchbase/operations/query_index_build_deferred.hxx +6 -6
  102. data/ext/couchbase/operations/query_index_create.hxx +10 -8
  103. data/ext/couchbase/operations/query_index_drop.hxx +8 -8
  104. data/ext/couchbase/operations/query_index_get_all.hxx +43 -39
  105. data/ext/couchbase/operations/rbac.hxx +40 -63
  106. data/ext/couchbase/operations/role_get_all.hxx +6 -6
  107. data/ext/couchbase/operations/scope_create.hxx +10 -10
  108. data/ext/couchbase/operations/scope_drop.hxx +9 -9
  109. data/ext/couchbase/operations/scope_get_all.hxx +8 -8
  110. data/ext/couchbase/operations/search_get_stats.hxx +5 -3
  111. data/ext/couchbase/operations/search_index.hxx +6 -15
  112. data/ext/couchbase/operations/search_index_analyze_document.hxx +11 -11
  113. data/ext/couchbase/operations/search_index_control_ingest.hxx +9 -9
  114. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +9 -9
  115. data/ext/couchbase/operations/search_index_control_query.hxx +9 -9
  116. data/ext/couchbase/operations/search_index_drop.hxx +11 -9
  117. data/ext/couchbase/operations/search_index_get.hxx +11 -9
  118. data/ext/couchbase/operations/search_index_get_all.hxx +11 -11
  119. data/ext/couchbase/operations/search_index_get_documents_count.hxx +10 -10
  120. data/ext/couchbase/operations/search_index_get_stats.hxx +10 -8
  121. data/ext/couchbase/operations/search_index_upsert.hxx +12 -10
  122. data/ext/couchbase/operations/user_drop.hxx +5 -5
  123. data/ext/couchbase/operations/user_get.hxx +7 -7
  124. data/ext/couchbase/operations/user_get_all.hxx +6 -6
  125. data/ext/couchbase/operations/user_upsert.hxx +9 -9
  126. data/ext/couchbase/operations/view_index_drop.hxx +10 -10
  127. data/ext/couchbase/operations/view_index_get.hxx +13 -15
  128. data/ext/couchbase/operations/view_index_get_all.hxx +17 -20
  129. data/ext/couchbase/operations/view_index_upsert.hxx +9 -7
  130. data/ext/couchbase/origin.hxx +14 -10
  131. data/ext/couchbase/platform/backtrace.c +1 -1
  132. data/ext/couchbase/platform/base64.cc +5 -5
  133. data/ext/couchbase/platform/base64.h +2 -5
  134. data/ext/couchbase/protocol/client_opcode.hxx +7 -4
  135. data/ext/couchbase/protocol/client_request.hxx +2 -2
  136. data/ext/couchbase/protocol/client_response.hxx +41 -16
  137. data/ext/couchbase/protocol/cmd_append.hxx +17 -16
  138. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +4 -4
  139. data/ext/couchbase/protocol/cmd_decrement.hxx +10 -11
  140. data/ext/couchbase/protocol/cmd_exists.hxx +12 -15
  141. data/ext/couchbase/protocol/cmd_get.hxx +11 -14
  142. data/ext/couchbase/protocol/cmd_get_and_lock.hxx +10 -12
  143. data/ext/couchbase/protocol/cmd_get_and_touch.hxx +10 -12
  144. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +13 -18
  145. data/ext/couchbase/protocol/cmd_get_collection_id.hxx +12 -15
  146. data/ext/couchbase/protocol/cmd_get_collections_manifest.hxx +12 -16
  147. data/ext/couchbase/protocol/cmd_get_error_map.hxx +14 -17
  148. data/ext/couchbase/protocol/cmd_hello.hxx +8 -10
  149. data/ext/couchbase/protocol/cmd_increment.hxx +9 -10
  150. data/ext/couchbase/protocol/cmd_insert.hxx +9 -9
  151. data/ext/couchbase/protocol/cmd_lookup_in.hxx +12 -13
  152. data/ext/couchbase/protocol/cmd_mutate_in.hxx +11 -11
  153. data/ext/couchbase/protocol/cmd_noop.hxx +16 -20
  154. data/ext/couchbase/protocol/cmd_prepend.hxx +9 -10
  155. data/ext/couchbase/protocol/cmd_remove.hxx +10 -13
  156. data/ext/couchbase/protocol/cmd_replace.hxx +7 -7
  157. data/ext/couchbase/protocol/cmd_sasl_auth.hxx +8 -10
  158. data/ext/couchbase/protocol/cmd_sasl_list_mechs.hxx +10 -15
  159. data/ext/couchbase/protocol/cmd_sasl_step.hxx +10 -12
  160. data/ext/couchbase/protocol/cmd_select_bucket.hxx +14 -18
  161. data/ext/couchbase/protocol/cmd_touch.hxx +8 -11
  162. data/ext/couchbase/protocol/cmd_unlock.hxx +10 -14
  163. data/ext/couchbase/protocol/cmd_upsert.hxx +8 -8
  164. data/ext/couchbase/protocol/datatype.hxx +3 -3
  165. data/ext/couchbase/protocol/durability_level.hxx +2 -2
  166. data/ext/couchbase/protocol/frame_info_id.hxx +4 -4
  167. data/ext/couchbase/protocol/hello_feature.hxx +2 -2
  168. data/ext/couchbase/protocol/magic.hxx +2 -2
  169. data/ext/couchbase/protocol/server_opcode.hxx +2 -2
  170. data/ext/couchbase/protocol/server_request.hxx +1 -1
  171. data/ext/couchbase/protocol/status.hxx +4 -7
  172. data/ext/couchbase/protocol/unsigned_leb128.h +5 -20
  173. data/ext/couchbase/service_type.hxx +4 -4
  174. data/ext/couchbase/tracing/constants.hxx +261 -0
  175. data/ext/couchbase/tracing/noop_tracer.hxx +50 -0
  176. data/ext/couchbase/tracing/request_tracer.hxx +77 -0
  177. data/ext/couchbase/tracing/threshold_logging_options.hxx +64 -0
  178. data/ext/couchbase/tracing/threshold_logging_tracer.hxx +366 -0
  179. data/ext/couchbase/utils/byteswap.hxx +1 -1
  180. data/ext/couchbase/utils/connection_string.hxx +21 -1
  181. data/ext/couchbase/utils/name_codec.hxx +41 -0
  182. data/ext/couchbase/utils/url_codec.hxx +236 -0
  183. data/ext/couchbase/version.hxx +1 -1
  184. data/ext/test/CMakeLists.txt +1 -0
  185. data/ext/test/test_native_trivial_query.cxx +60 -0
  186. data/ext/third_party/hdr_histogram_c/CMakeLists.txt +84 -0
  187. data/ext/third_party/hdr_histogram_c/COPYING.txt +121 -0
  188. data/ext/third_party/hdr_histogram_c/LICENSE.txt +41 -0
  189. data/ext/third_party/hdr_histogram_c/config.cmake.in +6 -0
  190. data/ext/third_party/hdr_histogram_c/src/CMakeLists.txt +83 -0
  191. data/ext/third_party/hdr_histogram_c/src/hdr_atomic.h +146 -0
  192. data/ext/third_party/hdr_histogram_c/src/hdr_encoding.c +322 -0
  193. data/ext/third_party/hdr_histogram_c/src/hdr_encoding.h +79 -0
  194. data/ext/third_party/hdr_histogram_c/src/hdr_endian.h +116 -0
  195. data/ext/third_party/hdr_histogram_c/src/hdr_histogram.c +1196 -0
  196. data/ext/third_party/hdr_histogram_c/src/hdr_histogram.h +516 -0
  197. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.c +1290 -0
  198. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.h +236 -0
  199. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log_no_op.c +171 -0
  200. data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.c +227 -0
  201. data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.h +109 -0
  202. data/ext/third_party/hdr_histogram_c/src/hdr_malloc.h +19 -0
  203. data/ext/third_party/hdr_histogram_c/src/hdr_tests.h +22 -0
  204. data/ext/third_party/hdr_histogram_c/src/hdr_thread.c +108 -0
  205. data/ext/third_party/hdr_histogram_c/src/hdr_thread.h +55 -0
  206. data/ext/third_party/hdr_histogram_c/src/hdr_time.c +98 -0
  207. data/ext/third_party/hdr_histogram_c/src/hdr_time.h +49 -0
  208. data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.c +143 -0
  209. data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.h +51 -0
  210. data/lib/couchbase/cluster.rb +1 -0
  211. data/lib/couchbase/errors.rb +3 -0
  212. data/lib/couchbase/libcouchbase.bundle +0 -0
  213. data/lib/couchbase/management/analytics_index_manager.rb +920 -226
  214. data/lib/couchbase/management/bucket_manager.rb +207 -69
  215. data/lib/couchbase/management/collection_manager.rb +173 -61
  216. data/lib/couchbase/management/query_index_manager.rb +357 -169
  217. data/lib/couchbase/options.rb +75 -3
  218. data/lib/couchbase/scope.rb +102 -0
  219. data/lib/couchbase/utils/time.rb +4 -0
  220. data/lib/couchbase/version.rb +6 -6
  221. metadata +48 -5
@@ -35,13 +35,13 @@ class query_cache
35
35
  void put(const std::string& statement, const std::string& prepared)
36
36
  {
37
37
  std::scoped_lock lock(store_mutex_);
38
- store_.emplace(statement, entry{ prepared });
38
+ store_.try_emplace(statement, entry{ prepared });
39
39
  }
40
40
 
41
41
  void put(const std::string& statement, const std::string& name, const std::string& encoded_plan)
42
42
  {
43
43
  std::scoped_lock lock(store_mutex_);
44
- store_.emplace(statement, entry{ name, encoded_plan });
44
+ store_.try_emplace(statement, entry{ name, encoded_plan });
45
45
  }
46
46
 
47
47
  std::optional<entry> get(const std::string& statement)
@@ -33,8 +33,7 @@ cap_duration(std::chrono::milliseconds uncapped, std::shared_ptr<Command> comman
33
33
  {
34
34
  auto theoretical_deadline = std::chrono::steady_clock::now() + uncapped;
35
35
  auto absolute_deadline = command->deadline.expiry();
36
- auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(theoretical_deadline - absolute_deadline);
37
- if (delta.count() > 0) {
36
+ if (auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(theoretical_deadline - absolute_deadline); delta.count() > 0) {
38
37
  auto capped = uncapped - delta;
39
38
  if (capped.count() < 0) {
40
39
  return uncapped; // something went wrong, return the uncapped one as a safety net
@@ -93,8 +92,7 @@ maybe_retry(std::shared_ptr<Manager> manager, std::shared_ptr<Command> command,
93
92
  return priv::retry_with_duration(manager, command, reason, priv::controlled_backoff(command->request.retries.retry_attempts));
94
93
  }
95
94
 
96
- retry_action action = command->request.retries.strategy.should_retry(command->request, reason);
97
- if (action.retry_requested) {
95
+ if (retry_action action = command->request.retries.strategy.should_retry(command->request, reason); action.retry_requested) {
98
96
  return priv::retry_with_duration(manager, command, reason, priv::cap_duration(action.duration, command));
99
97
  }
100
98
 
@@ -95,7 +95,7 @@ enum class retry_reason {
95
95
  views_no_active_partition,
96
96
  };
97
97
 
98
- constexpr inline bool
98
+ constexpr bool
99
99
  allows_non_idempotent_retry(retry_reason reason)
100
100
  {
101
101
  switch (reason) {
@@ -126,7 +126,7 @@ allows_non_idempotent_retry(retry_reason reason)
126
126
  return false;
127
127
  }
128
128
 
129
- constexpr inline bool
129
+ constexpr bool
130
130
  always_retry(retry_reason reason)
131
131
  {
132
132
  switch (reason) {
@@ -124,11 +124,6 @@ class exponential
124
124
  class best_effort
125
125
  {
126
126
  public:
127
- best_effort()
128
- : backoff_(std::chrono::milliseconds(1), 2, std::chrono::milliseconds(500))
129
- {
130
- }
131
-
132
127
  template<class Request>
133
128
  retry_action should_retry(Request& request, retry_reason reason)
134
129
  {
@@ -140,7 +135,7 @@ class best_effort
140
135
  }
141
136
 
142
137
  private:
143
- backoff::exponential backoff_;
138
+ backoff::exponential backoff_{ std::chrono::milliseconds(1), 2, std::chrono::milliseconds(500) };
144
139
  };
145
140
 
146
141
  class fail_fast
@@ -87,7 +87,7 @@ class plain_stream_impl : public stream_impl
87
87
  return stream_.is_open();
88
88
  }
89
89
 
90
- [[nodiscard]] virtual asio::ip::tcp::endpoint local_endpoint() const override
90
+ [[nodiscard]] asio::ip::tcp::endpoint local_endpoint() const override
91
91
  {
92
92
  std::error_code ec;
93
93
  auto res = stream_.local_endpoint(ec);
@@ -120,17 +120,17 @@ class plain_stream_impl : public stream_impl
120
120
  void async_connect(const asio::ip::tcp::resolver::results_type::endpoint_type& endpoint,
121
121
  std::function<void(std::error_code)>&& handler) override
122
122
  {
123
- return stream_.async_connect(endpoint, handler);
123
+ return stream_.async_connect(endpoint, std::move(handler));
124
124
  }
125
125
 
126
126
  void async_write(std::vector<asio::const_buffer>& buffers, std::function<void(std::error_code, std::size_t)>&& handler) override
127
127
  {
128
- return asio::async_write(stream_, buffers, handler);
128
+ return asio::async_write(stream_, buffers, std::move(handler));
129
129
  }
130
130
 
131
131
  void async_read_some(asio::mutable_buffer buffer, std::function<void(std::error_code, std::size_t)>&& handler) override
132
132
  {
133
- return stream_.async_read_some(buffer, handler);
133
+ return stream_.async_read_some(buffer, std::move(handler));
134
134
  }
135
135
  };
136
136
 
@@ -153,7 +153,7 @@ class tls_stream_impl : public stream_impl
153
153
  return stream_->lowest_layer().is_open();
154
154
  }
155
155
 
156
- [[nodiscard]] virtual asio::ip::tcp::endpoint local_endpoint() const override
156
+ [[nodiscard]] asio::ip::tcp::endpoint local_endpoint() const override
157
157
  {
158
158
  std::error_code ec;
159
159
  auto res = stream_->lowest_layer().local_endpoint(ec);
@@ -204,12 +204,12 @@ class tls_stream_impl : public stream_impl
204
204
 
205
205
  void async_write(std::vector<asio::const_buffer>& buffers, std::function<void(std::error_code, std::size_t)>&& handler) override
206
206
  {
207
- return asio::async_write(*stream_, buffers, handler);
207
+ return asio::async_write(*stream_, buffers, std::move(handler));
208
208
  }
209
209
 
210
210
  void async_read_some(asio::mutable_buffer buffer, std::function<void(std::error_code, std::size_t)>&& handler) override
211
211
  {
212
- return stream_->async_read_some(buffer, handler);
212
+ return stream_->async_read_some(buffer, std::move(handler));
213
213
  }
214
214
  };
215
215
 
@@ -0,0 +1,228 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2021 Couchbase, Inc.
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
+ #pragma once
19
+
20
+ #include <hdr_histogram.h>
21
+ #include <tao/json.hpp>
22
+
23
+ #include "logging_meter_options.hxx"
24
+ #include "meter.hxx"
25
+
26
+ namespace couchbase::metrics
27
+ {
28
+
29
+ class logging_value_recorder : public value_recorder
30
+ {
31
+ private:
32
+ std::string name_;
33
+ std::map<std::string, std::string> tags_;
34
+ hdr_histogram* histogram_{ nullptr };
35
+
36
+ void initialize_histogram()
37
+ {
38
+ histogram_ = nullptr;
39
+ hdr_init(/* minimum - 1 ns*/ 1,
40
+ /* maximum - 30 s*/ 30e9,
41
+ /* significant figures */ 3,
42
+ /* pointer */ &histogram_);
43
+ Expects(histogram_ != nullptr);
44
+ }
45
+
46
+ public:
47
+ logging_value_recorder(const std::string& name, const std::map<std::string, std::string>& tags)
48
+ : name_(name)
49
+ , tags_(tags)
50
+ {
51
+ initialize_histogram();
52
+ }
53
+
54
+ logging_value_recorder(const logging_value_recorder& other)
55
+ : value_recorder()
56
+ , name_(other.name_)
57
+ , tags_(other.tags_)
58
+ , histogram_(nullptr)
59
+ {
60
+ initialize_histogram();
61
+ }
62
+
63
+ logging_value_recorder(logging_value_recorder&& other)
64
+ : value_recorder()
65
+ , name_(std::move(other.name_))
66
+ , tags_(std::move(other.tags_))
67
+ , histogram_(nullptr)
68
+ {
69
+ initialize_histogram();
70
+ }
71
+
72
+ logging_value_recorder& operator=(const logging_value_recorder& other)
73
+ {
74
+ if (this == &other) {
75
+ return *this;
76
+ }
77
+ name_ = other.name_;
78
+ tags_ = other.tags_;
79
+ initialize_histogram();
80
+ return *this;
81
+ }
82
+
83
+ logging_value_recorder& operator=(logging_value_recorder&& other)
84
+ {
85
+ if (this == &other) {
86
+ return *this;
87
+ }
88
+ name_ = std::move(other.name_);
89
+ tags_ = std::move(other.tags_);
90
+ initialize_histogram();
91
+ return *this;
92
+ }
93
+
94
+ ~logging_value_recorder() override
95
+ {
96
+ if (histogram_ != nullptr) {
97
+ hdr_close(histogram_);
98
+ histogram_ = nullptr;
99
+ }
100
+ }
101
+
102
+ void record_value(std::int64_t value) override
103
+ {
104
+ if (histogram_ == nullptr) {
105
+ return;
106
+ }
107
+ // Expects(histogram_ != nullptr);
108
+ hdr_record_value(histogram_, value);
109
+ }
110
+
111
+ [[nodiscard]] tao::json::value emit() const
112
+ {
113
+ auto total_count = histogram_->total_count;
114
+ auto val_50_0 = hdr_value_at_percentile(histogram_, 50.0);
115
+ auto val_90_0 = hdr_value_at_percentile(histogram_, 90.0);
116
+ auto val_99_0 = hdr_value_at_percentile(histogram_, 99.0);
117
+ auto val_99_9 = hdr_value_at_percentile(histogram_, 99.9);
118
+ auto val_100_0 = hdr_value_at_percentile(histogram_, 100.0);
119
+
120
+ hdr_reset(histogram_);
121
+
122
+ return {
123
+ { "total_count", total_count },
124
+ { "percentiles_us",
125
+ {
126
+ { "50.0", val_50_0 },
127
+ { "90.0", val_90_0 },
128
+ { "99.0", val_99_0 },
129
+ { "99.9", val_99_9 },
130
+ { "100.0", val_100_0 },
131
+ } },
132
+ };
133
+ }
134
+ };
135
+
136
+ class logging_meter : public meter
137
+ {
138
+ private:
139
+ asio::steady_timer emit_report_;
140
+ logging_meter_options options_;
141
+ std::map<std::string, std::map<std::string, logging_value_recorder>> recorders_{};
142
+
143
+ void log_report() const
144
+ {
145
+ tao::json::value report{
146
+ {
147
+ "meta",
148
+ {
149
+
150
+ { "emit_interval_s", std::chrono::duration_cast<std::chrono::seconds>(options_.emit_interval).count() },
151
+ #if BACKEND_DEBUG_BUILD
152
+ { "emit_interval_ms", options_.emit_interval.count() },
153
+ #endif
154
+ },
155
+ },
156
+ };
157
+ for (const auto& [service, operations] : recorders_) {
158
+ for (const auto& [operation, recorder] : operations) {
159
+ report["operations"][service][operation] = recorder.emit();
160
+ }
161
+ }
162
+ spdlog::info("Metrics: {}", tao::json::to_string(report));
163
+ }
164
+
165
+ void rearm_reporter()
166
+ {
167
+ emit_report_.expires_after(options_.emit_interval);
168
+ emit_report_.async_wait([this](std::error_code ec) {
169
+ if (ec == asio::error::operation_aborted) {
170
+ return;
171
+ }
172
+ log_report();
173
+ rearm_reporter();
174
+ });
175
+ }
176
+
177
+ public:
178
+ logging_meter(asio::io_context& ctx, logging_meter_options options)
179
+ : emit_report_(ctx)
180
+ , options_(options)
181
+ {
182
+ }
183
+
184
+ ~logging_meter() override
185
+ {
186
+ emit_report_.cancel();
187
+ log_report();
188
+ }
189
+
190
+ void start()
191
+ {
192
+ rearm_reporter();
193
+ }
194
+
195
+ value_recorder* get_value_recorder(const std::string& name, const std::map<std::string, std::string>& tags) override
196
+ {
197
+ static noop_value_recorder noop_recorder{};
198
+
199
+ static std::string meter_name = "db.couchbase.operations";
200
+ if (name != meter_name) {
201
+ return &noop_recorder;
202
+ }
203
+
204
+ static std::string service_tag = "db.couchbase.service";
205
+ auto service = tags.find(service_tag);
206
+ if (service == tags.end()) {
207
+ return &noop_recorder;
208
+ }
209
+ auto& service_recorders = recorders_[service->second];
210
+
211
+ static std::string operation_tag = "db.operation";
212
+ auto operation = tags.find(operation_tag);
213
+ if (operation == tags.end()) {
214
+ return &noop_recorder;
215
+ }
216
+
217
+ auto recorder = service_recorders.find(operation->second);
218
+ if (recorder != service_recorders.end()) {
219
+ return &recorder->second;
220
+ }
221
+
222
+ service_recorders.emplace(operation->second, logging_value_recorder(operation->second, tags));
223
+ recorder = service_recorders.find(operation->second);
224
+ return &recorder->second;
225
+ }
226
+ };
227
+
228
+ } // namespace couchbase::metrics
@@ -0,0 +1,28 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2021 Couchbase, Inc.
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
+ #pragma once
19
+
20
+ #include <chrono>
21
+
22
+ namespace couchbase::metrics
23
+ {
24
+ struct logging_meter_options {
25
+ std::chrono::milliseconds emit_interval{ std::chrono::minutes{ 10 } };
26
+ };
27
+
28
+ } // namespace couchbase::metrics
@@ -0,0 +1,49 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2021 Couchbase, Inc.
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
+ #pragma once
19
+
20
+ namespace couchbase::metrics
21
+ {
22
+
23
+ class value_recorder
24
+ {
25
+ public:
26
+ value_recorder() = default;
27
+ value_recorder(const value_recorder& other) = default;
28
+ value_recorder(value_recorder&& other) = default;
29
+ value_recorder& operator=(const value_recorder& other) = default;
30
+ value_recorder& operator=(value_recorder&& other) = default;
31
+ virtual ~value_recorder() = default;
32
+
33
+ virtual void record_value(std::int64_t value) = 0;
34
+ };
35
+
36
+ class meter
37
+ {
38
+ public:
39
+ meter() = default;
40
+ meter(const meter& other) = default;
41
+ meter(meter&& other) = default;
42
+ meter& operator=(const meter& other) = default;
43
+ meter& operator=(meter&& other) = default;
44
+ virtual ~meter() = default;
45
+
46
+ virtual value_recorder* get_value_recorder(const std::string& /* name */, const std::map<std::string, std::string>& /* tags */) = 0;
47
+ };
48
+
49
+ } // namespace couchbase::metrics
@@ -0,0 +1,43 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2021 Couchbase, Inc.
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
+ #pragma once
19
+
20
+ #include "meter.hxx"
21
+
22
+ namespace couchbase::metrics
23
+ {
24
+
25
+ class noop_value_recorder : public value_recorder
26
+ {
27
+ public:
28
+ void record_value(std::int64_t /* value */) override
29
+ {
30
+ }
31
+ };
32
+
33
+ class noop_meter : public meter
34
+ {
35
+ public:
36
+ value_recorder* get_value_recorder(const std::string& /* name */, const std::map<std::string, std::string>& /* tags */)
37
+ {
38
+ static noop_value_recorder instance{};
39
+ return &instance;
40
+ }
41
+ };
42
+
43
+ } // namespace couchbase::metrics