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
@@ -0,0 +1,64 @@
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
+ #include <service_type.hxx>
23
+
24
+ namespace couchbase::tracing
25
+ {
26
+ struct threshold_logging_options {
27
+ std::chrono::milliseconds orphaned_emit_interval{ std::chrono::seconds{ 10 } };
28
+ std::size_t orphaned_sample_size{ 64 };
29
+
30
+ std::chrono::milliseconds threshold_emit_interval{ std::chrono::seconds{ 10 } };
31
+ std::size_t threshold_sample_size{ 64 };
32
+ std::chrono::milliseconds key_value_threshold{ 500 };
33
+ std::chrono::milliseconds query_threshold{ 1'000 };
34
+ std::chrono::milliseconds view_threshold{ 1'000 };
35
+ std::chrono::milliseconds search_threshold{ 1'000 };
36
+ std::chrono::milliseconds analytics_threshold{ 1'000 };
37
+ std::chrono::milliseconds management_threshold{ 1'000 };
38
+
39
+ [[nodiscard]] std::chrono::milliseconds threshold_for_service(service_type service) const
40
+ {
41
+ switch (service) {
42
+ case service_type::key_value:
43
+ return key_value_threshold;
44
+
45
+ case service_type::query:
46
+ return query_threshold;
47
+
48
+ case service_type::analytics:
49
+ return analytics_threshold;
50
+
51
+ case service_type::search:
52
+ return search_threshold;
53
+
54
+ case service_type::view:
55
+ return view_threshold;
56
+
57
+ case service_type::management:
58
+ return management_threshold;
59
+ }
60
+ return {};
61
+ }
62
+ };
63
+
64
+ } // namespace couchbase::tracing
@@ -0,0 +1,366 @@
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
+ #include <tao/json.hpp>
23
+
24
+ #include "request_tracer.hxx"
25
+ #include "threshold_logging_options.hxx"
26
+ #include "version.hxx"
27
+
28
+ namespace couchbase::tracing
29
+ {
30
+ namespace impl
31
+ {
32
+ struct reported_span {
33
+ std::chrono::milliseconds duration;
34
+ tao::json::value payload;
35
+
36
+ bool operator<(const reported_span& other) const
37
+ {
38
+ return duration < other.duration;
39
+ }
40
+ };
41
+
42
+ template<typename T>
43
+ class fixed_queue : private std::priority_queue<T>
44
+ {
45
+ private:
46
+ std::size_t capacity_{};
47
+
48
+ public:
49
+ explicit fixed_queue(std::size_t capacity)
50
+ : std::priority_queue<T>()
51
+ , capacity_(capacity)
52
+ {
53
+ }
54
+
55
+ using std::priority_queue<T>::pop;
56
+ using std::priority_queue<T>::size;
57
+ using std::priority_queue<T>::empty;
58
+ using std::priority_queue<T>::top;
59
+
60
+ void emplace(const T&& item)
61
+ {
62
+ std::priority_queue<T>::emplace(item);
63
+ if (size() > capacity_) {
64
+ pop();
65
+ }
66
+ }
67
+ };
68
+
69
+ using fixed_span_queue = fixed_queue<reported_span>;
70
+ } // namespace impl
71
+
72
+ class threshold_logging_tracer;
73
+
74
+ class threshold_logging_span : public request_span
75
+ {
76
+ private:
77
+ std::chrono::system_clock::time_point start_{ std::chrono::system_clock::now() };
78
+ std::string id_{ uuid::to_string(uuid::random()) };
79
+ std::map<std::string, std::uint64_t> integer_tags_{};
80
+ std::map<std::string, std::string> string_tags_{
81
+ { attributes::system, "couchbase" },
82
+ { attributes::span_kind, "client" },
83
+ { attributes::component, couchbase::sdk_id() },
84
+ };
85
+ std::chrono::milliseconds duration_{ 0 };
86
+ std::uint64_t last_server_duration_us_{ 0 };
87
+ std::uint64_t total_server_duration_us_{ 0 };
88
+
89
+ std::string name_;
90
+ threshold_logging_tracer* tracer_;
91
+
92
+ public:
93
+ threshold_logging_span(const std::string& name, threshold_logging_tracer* tracer)
94
+ : request_span(name)
95
+ , tracer_{ tracer }
96
+ {
97
+ }
98
+
99
+ void add_tag(const std::string& name, std::uint64_t value) override
100
+ {
101
+ if (name == tracing::attributes::server_duration) {
102
+ last_server_duration_us_ = value;
103
+ total_server_duration_us_ += value;
104
+ }
105
+ integer_tags_.try_emplace(name, value);
106
+ }
107
+
108
+ void add_tag(const std::string& name, const std::string& value) override
109
+ {
110
+ string_tags_.try_emplace(name, value);
111
+ }
112
+
113
+ void end() override;
114
+
115
+ [[nodiscard]] const auto& string_tags() const
116
+ {
117
+ return string_tags_;
118
+ }
119
+
120
+ [[nodiscard]] std::chrono::milliseconds duration() const
121
+ {
122
+ return duration_;
123
+ }
124
+
125
+ [[nodiscard]] std::uint64_t last_server_duration_us() const
126
+ {
127
+ return last_server_duration_us_;
128
+ }
129
+
130
+ [[nodiscard]] std::uint64_t total_server_duration_us() const
131
+ {
132
+ return total_server_duration_us_;
133
+ }
134
+
135
+ [[nodiscard]] bool orphan() const
136
+ {
137
+ return string_tags_.find(tracing::attributes::orphan) != string_tags_.end();
138
+ }
139
+
140
+ [[nodiscard]] bool is_key_value() const
141
+ {
142
+ auto service_tag = string_tags_.find(tracing::attributes::service);
143
+ if (service_tag == string_tags_.end()) {
144
+ return false;
145
+ }
146
+ return service_tag->second == tracing::service::key_value;
147
+ }
148
+
149
+ [[nodiscard]] std::optional<service_type> service() const
150
+ {
151
+ auto service_tag = string_tags_.find(tracing::attributes::service);
152
+ if (service_tag == string_tags_.end()) {
153
+ return {};
154
+ }
155
+ const auto& service_name = service_tag->second;
156
+ if (service_name == tracing::service::key_value) {
157
+ return service_type::key_value;
158
+ }
159
+ if (service_name == tracing::service::query) {
160
+ return service_type::query;
161
+ }
162
+ if (service_name == tracing::service::view) {
163
+ return service_type::view;
164
+ }
165
+ if (service_name == tracing::service::search) {
166
+ return service_type::search;
167
+ }
168
+ if (service_name == tracing::service::analytics) {
169
+ return service_type::analytics;
170
+ }
171
+ if (service_name == tracing::service::management) {
172
+ return service_type::management;
173
+ }
174
+ return {};
175
+ }
176
+ };
177
+
178
+ class threshold_logging_tracer : public request_tracer
179
+ {
180
+ private:
181
+ asio::steady_timer emit_orphan_report_;
182
+ asio::steady_timer emit_threshold_report_;
183
+ threshold_logging_options options_;
184
+ impl::fixed_span_queue orphan_queue_;
185
+ std::map<service_type, impl::fixed_span_queue> threshold_queues_{};
186
+
187
+ void add_orphan(threshold_logging_span* span)
188
+ {
189
+ orphan_queue_.emplace(convert(span));
190
+ }
191
+
192
+ void check_threshold(threshold_logging_span* span)
193
+ {
194
+ auto service = span->service();
195
+ if (!service.has_value()) {
196
+ return;
197
+ }
198
+ if (span->duration() > options_.threshold_for_service(service.value())) {
199
+ auto queue = threshold_queues_.find(service.value());
200
+ if (queue != threshold_queues_.end()) {
201
+ queue->second.emplace(convert(span));
202
+ }
203
+ }
204
+ }
205
+
206
+ impl::reported_span convert(threshold_logging_span* span)
207
+ {
208
+ tao::json::value entry{ { "operation_name", span->name() },
209
+ { "total_duration_us", std::chrono::duration_cast<std::chrono::microseconds>(span->duration()).count() } };
210
+ if (span->is_key_value()) {
211
+ entry["last_server_duration_us"] = span->last_server_duration_us();
212
+ entry["total_server_duration_us"] = span->total_server_duration_us();
213
+ }
214
+
215
+ const auto& tags = span->string_tags();
216
+ auto pair = tags.find(attributes::operation_id);
217
+ if (pair != tags.end()) {
218
+ entry["last_operation_id"] = pair->second;
219
+ }
220
+
221
+ pair = tags.find(attributes::local_id);
222
+ if (pair != tags.end()) {
223
+ entry["last_local_id"] = pair->second;
224
+ }
225
+
226
+ pair = tags.find(attributes::local_socket);
227
+ if (pair != tags.end()) {
228
+ entry["last_local_socket"] = pair->second;
229
+ }
230
+
231
+ pair = tags.find(attributes::remote_socket);
232
+ if (pair != tags.end()) {
233
+ entry["last_remote_socket"] = pair->second;
234
+ }
235
+
236
+ return { span->duration(), std::move(entry) };
237
+ }
238
+
239
+ void log_orphan_report()
240
+ {
241
+ if (orphan_queue_.empty()) {
242
+ return;
243
+ }
244
+ auto queue = impl::fixed_span_queue(options_.orphaned_sample_size);
245
+ std::swap(orphan_queue_, queue);
246
+ tao::json::value report
247
+ {
248
+ { "count", queue.size() },
249
+ #if BACKEND_DEBUG_BUILD
250
+ { "emit_interval_ms", options_.orphaned_emit_interval.count() }, { "sample_size", options_.orphaned_sample_size },
251
+ #endif
252
+ };
253
+ tao::json::value entries = tao::json::empty_array;
254
+ while (!queue.empty()) {
255
+ entries.emplace_back(queue.top().payload);
256
+ queue.pop();
257
+ }
258
+ report["top"] = entries;
259
+ spdlog::warn("Orphan responses observed: {}", tao::json::to_string(report));
260
+ }
261
+
262
+ void log_threshold_report()
263
+ {
264
+ for (auto& [service, threshold_queue] : threshold_queues_) {
265
+ if (threshold_queue.empty()) {
266
+ continue;
267
+ }
268
+ auto queue = impl::fixed_span_queue(options_.threshold_sample_size);
269
+ std::swap(threshold_queue, queue);
270
+ tao::json::value report
271
+ {
272
+ { "count", queue.size() }, { "service", fmt::format("{}", service) },
273
+ #if BACKEND_DEBUG_BUILD
274
+ { "emit_interval_ms", options_.threshold_emit_interval.count() }, { "sample_size", options_.threshold_sample_size },
275
+ { "threshold_ms",
276
+ std::chrono::duration_cast<std::chrono::microseconds>(options_.threshold_for_service(service)).count() },
277
+ #endif
278
+ };
279
+ tao::json::value entries = tao::json::empty_array;
280
+ while (!queue.empty()) {
281
+ entries.emplace_back(queue.top().payload);
282
+ queue.pop();
283
+ }
284
+ report["top"] = entries;
285
+ spdlog::warn("Operations over threshold: {}", tao::json::to_string(report));
286
+ }
287
+ }
288
+
289
+ void rearm_orphan_reporter()
290
+ {
291
+ emit_orphan_report_.expires_after(options_.orphaned_emit_interval);
292
+ emit_orphan_report_.async_wait([this](std::error_code ec) {
293
+ if (ec == asio::error::operation_aborted) {
294
+ return;
295
+ }
296
+ log_orphan_report();
297
+ rearm_orphan_reporter();
298
+ });
299
+ }
300
+
301
+ void rearm_threshold_reporter()
302
+ {
303
+ emit_threshold_report_.expires_after(options_.threshold_emit_interval);
304
+ emit_threshold_report_.async_wait([this](std::error_code ec) {
305
+ if (ec == asio::error::operation_aborted) {
306
+ return;
307
+ }
308
+ log_threshold_report();
309
+ rearm_threshold_reporter();
310
+ });
311
+ }
312
+
313
+ public:
314
+ threshold_logging_tracer(asio::io_context& ctx, threshold_logging_options options)
315
+ : request_tracer()
316
+ , emit_orphan_report_(ctx)
317
+ , emit_threshold_report_(ctx)
318
+ , options_{ options }
319
+ , orphan_queue_{ options_.orphaned_sample_size }
320
+ {
321
+ threshold_queues_.emplace(service_type::key_value, options_.threshold_sample_size);
322
+ threshold_queues_.emplace(service_type::query, options_.threshold_sample_size);
323
+ threshold_queues_.emplace(service_type::view, options_.threshold_sample_size);
324
+ threshold_queues_.emplace(service_type::search, options_.threshold_sample_size);
325
+ threshold_queues_.emplace(service_type::analytics, options_.threshold_sample_size);
326
+ threshold_queues_.emplace(service_type::management, options_.threshold_sample_size);
327
+ }
328
+
329
+ void start()
330
+ {
331
+ rearm_orphan_reporter();
332
+ rearm_threshold_reporter();
333
+ }
334
+
335
+ ~threshold_logging_tracer() override
336
+ {
337
+ emit_orphan_report_.cancel();
338
+ emit_threshold_report_.cancel();
339
+ log_orphan_report();
340
+ log_threshold_report();
341
+ }
342
+
343
+ request_span* start_span(std::string name, request_span* /* parent */) override
344
+ {
345
+ return new threshold_logging_span(name, this);
346
+ }
347
+
348
+ void report(threshold_logging_span* span)
349
+ {
350
+ if (span->orphan()) {
351
+ add_orphan(span);
352
+ } else {
353
+ check_threshold(span);
354
+ }
355
+ }
356
+ };
357
+
358
+ void
359
+ threshold_logging_span::end()
360
+ {
361
+ duration_ = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start_);
362
+ tracer_->report(this);
363
+ delete this;
364
+ }
365
+
366
+ } // namespace couchbase::tracing
@@ -19,7 +19,7 @@
19
19
 
20
20
  namespace couchbase::utils
21
21
  {
22
- static inline std::uint64_t
22
+ static constexpr std::uint64_t
23
23
  byte_swap_64(std::uint64_t val)
24
24
  {
25
25
  std::uint64_t ret = 0U;
@@ -357,6 +357,26 @@ extract_options(connection_string& connstr)
357
357
  } else if (param.second == "false" || param.second == "no" || param.second == "off") {
358
358
  connstr.options.enable_compression = false;
359
359
  }
360
+ } else if (param.first == "enable_tracing") {
361
+ /**
362
+ * true - use threshold_logging_tracer
363
+ * false - use noop_tracer
364
+ */
365
+ if (param.second == "true" || param.second == "yes" || param.second == "on") {
366
+ connstr.options.enable_tracing = true;
367
+ } else if (param.second == "false" || param.second == "no" || param.second == "off") {
368
+ connstr.options.enable_tracing = false;
369
+ }
370
+ } else if (param.first == "enable_metrics") {
371
+ /**
372
+ * true - use logging_meter
373
+ * false - use noop_meter
374
+ */
375
+ if (param.second == "true" || param.second == "yes" || param.second == "on") {
376
+ connstr.options.enable_metrics = true;
377
+ } else if (param.second == "false" || param.second == "no" || param.second == "off") {
378
+ connstr.options.enable_metrics = false;
379
+ }
360
380
  } else {
361
381
  spdlog::warn(R"(unknown parameter "{}" in connection string (value "{}"))", param.first, param.second);
362
382
  }
@@ -388,7 +408,7 @@ parse_connection_string(const std::string& input)
388
408
  try {
389
409
  connection_string::node node{};
390
410
  tao::json::pegtl::parse<priv::grammar, priv::action>(in, res, node);
391
- } catch (tao::json::pegtl::parse_error& e) {
411
+ } catch (const tao::json::pegtl::parse_error& e) {
392
412
  for (const auto& position : e.positions()) {
393
413
  if (position.source == __FUNCTION__) {
394
414
  res.error = fmt::format(