couchbase 3.7.0-x86_64-linux → 3.8.0-x86_64-linux

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/active_support/cache/couchbase_store.rb +6 -6
  4. data/lib/couchbase/3.2/libcouchbase.so +0 -0
  5. data/lib/couchbase/3.3/libcouchbase.so +0 -0
  6. data/lib/couchbase/3.4/libcouchbase.so +0 -0
  7. data/lib/couchbase/{3.1 → 4.0}/libcouchbase.so +0 -0
  8. data/lib/couchbase/authenticator.rb +14 -0
  9. data/lib/couchbase/binary_collection.rb +37 -22
  10. data/lib/couchbase/bucket.rb +46 -31
  11. data/lib/couchbase/cluster.rb +146 -61
  12. data/lib/couchbase/collection.rb +257 -186
  13. data/lib/couchbase/datastructures/couchbase_list.rb +81 -50
  14. data/lib/couchbase/datastructures/couchbase_map.rb +86 -50
  15. data/lib/couchbase/datastructures/couchbase_queue.rb +64 -38
  16. data/lib/couchbase/datastructures/couchbase_set.rb +57 -41
  17. data/lib/couchbase/deprecations.rb +1 -1
  18. data/lib/couchbase/diagnostics.rb +8 -8
  19. data/lib/couchbase/errors.rb +6 -0
  20. data/lib/couchbase/libcouchbase.rb +1 -1
  21. data/lib/couchbase/management/analytics_index_manager.rb +90 -59
  22. data/lib/couchbase/management/bucket_manager.rb +73 -45
  23. data/lib/couchbase/management/collection_manager.rb +86 -43
  24. data/lib/couchbase/management/collection_query_index_manager.rb +56 -33
  25. data/lib/couchbase/management/query_index_manager.rb +88 -36
  26. data/lib/couchbase/management/scope_search_index_manager.rb +119 -52
  27. data/lib/couchbase/management/search_index_manager.rb +401 -178
  28. data/lib/couchbase/management/user_manager.rb +343 -174
  29. data/lib/couchbase/management/view_index_manager.rb +166 -73
  30. data/lib/couchbase/metrics/logging_meter.rb +108 -0
  31. data/lib/couchbase/metrics/logging_value_recorder.rb +50 -0
  32. data/lib/couchbase/metrics/meter.rb +27 -0
  33. data/lib/couchbase/metrics/noop_meter.rb +30 -0
  34. data/lib/couchbase/metrics/noop_value_recorder.rb +27 -0
  35. data/lib/couchbase/metrics/value_recorder.rb +25 -0
  36. data/lib/couchbase/options.rb +69 -3
  37. data/lib/couchbase/protostellar/cluster.rb +3 -0
  38. data/lib/couchbase/scope.rb +62 -48
  39. data/lib/couchbase/search_options.rb +18 -18
  40. data/lib/couchbase/tracing/noop_span.rb +29 -0
  41. data/lib/couchbase/tracing/noop_tracer.rb +29 -0
  42. data/lib/couchbase/tracing/request_span.rb +34 -0
  43. data/lib/couchbase/tracing/request_tracer.rb +28 -0
  44. data/lib/couchbase/tracing/threshold_logging_span.rb +112 -0
  45. data/lib/couchbase/tracing/threshold_logging_tracer.rb +231 -0
  46. data/lib/couchbase/utils/hdr_histogram.rb +55 -0
  47. data/lib/couchbase/utils/observability.rb +257 -0
  48. data/lib/couchbase/utils/observability_constants.rb +200 -0
  49. data/lib/couchbase/utils/stdlib_logger_adapter.rb +1 -3
  50. data/lib/couchbase/version.rb +1 -1
  51. data/lib/couchbase.rb +2 -2
  52. metadata +37 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 130d0c58154d82f0e434df21db4a08c2d7062290bb3c17fc78a329416338ce2f
4
- data.tar.gz: 44d3dc2dc11b2caa2a2dcfd87a489810ea6a86806f27568b9ae14f6a619f0dfc
3
+ metadata.gz: f88e9fe75a923fce2ff39f382423e702e5abd50c3eb19993b5c880c10ba950b8
4
+ data.tar.gz: 2c703927ea6ff1b8df8ebbf8681423281d2f1b4df15b43d2422b0826fca1f30c
5
5
  SHA512:
6
- metadata.gz: 23219ceb9a9d6f8059264a4a480b4408fedc4d68c67152f0b0af7e7250887a43859fbe012f424040acb4b2170edde31f2e7af43bc94b59a235b12364c75964cc
7
- data.tar.gz: 40b17592a5c6b87582c670429bf5144e46f61fdcd0de0c9d6e7a6b5b7f4e53e38d25f88577f6bdff79b492eccd79a7d0829c3db3a8d8d2fbbe05c8d8752d0877
6
+ metadata.gz: 65c8510b8f154fd94db09240a3a3edf8fd848d3acfa02aa46048a2ad43d48901dd0a45c3f1e68b1b2e9a2db5d9f834165550fca8542c1af80e01a99312806b21
7
+ data.tar.gz: 37871be1453e41500df90f9242cb182579295d5a4bd8bef7c43eaa764aac5311cbb72af1dc77e0a5405ae9a410408ec14291b415ada2b4ccc95cca69af3bd0d5
data/README.md CHANGED
@@ -9,7 +9,7 @@ This repository contains the third generation of the official Couchbase SDK for
9
9
 
10
10
  ## Support and Feedback
11
11
 
12
- If you find an issue, please file it in [our JIRA issue tracker](https://couchbase.com/issues/browse/RCBC). Also you are
12
+ If you find an issue, please file it in [our JIRA issue tracker](https://jira.issues.couchbase.com/browse/RCBC). Also you are
13
13
  always welcome on [our forum](https://forums.couchbase.com/c/ruby-sdk) and [Discord](https://discord.com/invite/sQ5qbPZuTh).
14
14
 
15
15
  Please attach version information to the ticket/post. To obtain this information, use the following command:
@@ -18,12 +18,12 @@ Please attach version information to the ticket/post. To obtain this information
18
18
 
19
19
  ## Installation
20
20
 
21
- The library has been tested with MRI 3.1, 3.2, 3.3 and 3.4. Supported platforms are Linux and MacOS.
21
+ The library has been tested with MRI 3.2, 3.3, 3.4 and 4.0. Supported platforms are Linux and MacOS.
22
22
 
23
23
  Add this line to your application's Gemfile:
24
24
 
25
25
  ```ruby
26
- gem "couchbase", "3.7.0"
26
+ gem "couchbase", "3.8.0"
27
27
  ```
28
28
 
29
29
  And then execute:
@@ -180,11 +180,11 @@ module ActiveSupport
180
180
  end
181
181
  end
182
182
 
183
- def serialize_entry(entry, raw: false, **options)
183
+ def serialize_entry(entry, raw: false, **)
184
184
  if raw
185
185
  entry.value.to_s
186
186
  else
187
- super(entry, **options)
187
+ super(entry, **)
188
188
  end
189
189
  end
190
190
 
@@ -195,8 +195,8 @@ module ActiveSupport
195
195
  end
196
196
 
197
197
  # Reads an entry from the cache
198
- def read_entry(key, **options)
199
- deserialize_entry(read_serialized_entry(key, **options), **options)
198
+ def read_entry(key, **)
199
+ deserialize_entry(read_serialized_entry(key, **), **)
200
200
  end
201
201
 
202
202
  def read_serialized_entry(key, **)
@@ -228,8 +228,8 @@ module ActiveSupport
228
228
  end
229
229
 
230
230
  # Writes an entry to the cache
231
- def write_entry(key, entry, raw: false, **options)
232
- write_serialized_entry(key, serialize_entry(entry, raw: raw, **options), raw: raw, **options)
231
+ def write_entry(key, entry, raw: false, **)
232
+ write_serialized_entry(key, serialize_entry(entry, raw: raw, **), raw: raw, **)
233
233
  end
234
234
 
235
235
  def write_serialized_entry(key, payload, expires_in: nil, race_condition_ttl: nil, raw: false, **)
Binary file
Binary file
Binary file
@@ -63,4 +63,18 @@ module Couchbase
63
63
  @key_path = key_path
64
64
  end
65
65
  end
66
+
67
+ # Authenticator using a JSON Web Token (JWT)
68
+ #
69
+ # @!macro uncommitted
70
+ class JWTAuthenticator
71
+ attr_accessor :token
72
+
73
+ # Creates a new authenticator with a JSON Web Token (JWT)
74
+ #
75
+ # @param [String] token the JWT
76
+ def initialize(token)
77
+ @token = token
78
+ end
79
+ end
66
80
  end
@@ -23,9 +23,12 @@ module Couchbase
23
23
  alias inspect to_s
24
24
 
25
25
  # @param [Couchbase::Collection] collection parent collection
26
+ #
27
+ # @api private
26
28
  def initialize(collection)
27
29
  @collection = collection
28
30
  @backend = collection.instance_variable_get(:@backend)
31
+ @observability = collection.instance_variable_get(:@observability)
29
32
  end
30
33
 
31
34
  # Appends binary content to the document
@@ -41,11 +44,14 @@ module Couchbase
41
44
  #
42
45
  # @return [Collection::MutationResult]
43
46
  def append(id, content, options = Options::Append::DEFAULT)
44
- resp = @backend.document_append(@collection.bucket_name, @collection.scope_name, @collection.name,
45
- id, content, options.to_backend)
46
- Collection::MutationResult.new do |res|
47
- res.cas = resp[:cas]
48
- res.mutation_token = @collection.send(:extract_mutation_token, resp)
47
+ @observability.record_operation(Observability::OP_APPEND, options.parent_span, self, :kv) do |obs_handler|
48
+ obs_handler.add_durability_level(options.durability_level)
49
+ resp = @backend.document_append(@collection.bucket_name, @collection.scope_name, @collection.name,
50
+ id, content, options.to_backend, obs_handler)
51
+ Collection::MutationResult.new do |res|
52
+ res.cas = resp[:cas]
53
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
54
+ end
49
55
  end
50
56
  end
51
57
 
@@ -62,11 +68,14 @@ module Couchbase
62
68
  #
63
69
  # @return [Collection::MutationResult]
64
70
  def prepend(id, content, options = Options::Prepend::DEFAULT)
65
- resp = @backend.document_prepend(@collection.bucket_name, @collection.scope_name, @collection.name,
66
- id, content, options.to_backend)
67
- Collection::MutationResult.new do |res|
68
- res.cas = resp[:cas]
69
- res.mutation_token = @collection.send(:extract_mutation_token, resp)
71
+ @observability.record_operation(Observability::OP_PREPEND, options.parent_span, self, :kv) do |obs_handler|
72
+ obs_handler.add_durability_level(options.durability_level)
73
+ resp = @backend.document_prepend(@collection.bucket_name, @collection.scope_name, @collection.name,
74
+ id, content, options.to_backend, obs_handler)
75
+ Collection::MutationResult.new do |res|
76
+ res.cas = resp[:cas]
77
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
78
+ end
70
79
  end
71
80
  end
72
81
 
@@ -83,12 +92,15 @@ module Couchbase
83
92
  #
84
93
  # @return [CounterResult]
85
94
  def increment(id, options = Options::Increment::DEFAULT)
86
- resp = @backend.document_increment(@collection.bucket_name, @collection.scope_name, @collection.name, id,
87
- options.to_backend)
88
- CounterResult.new do |res|
89
- res.cas = resp[:cas]
90
- res.content = resp[:content]
91
- res.mutation_token = @collection.send(:extract_mutation_token, resp)
95
+ @observability.record_operation(Observability::OP_INCREMENT, options.parent_span, self, :kv) do |obs_handler|
96
+ obs_handler.add_durability_level(options.durability_level)
97
+ resp = @backend.document_increment(@collection.bucket_name, @collection.scope_name, @collection.name, id,
98
+ options.to_backend, obs_handler)
99
+ CounterResult.new do |res|
100
+ res.cas = resp[:cas]
101
+ res.content = resp[:content]
102
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
103
+ end
92
104
  end
93
105
  end
94
106
 
@@ -105,12 +117,15 @@ module Couchbase
105
117
  #
106
118
  # @return [CounterResult]
107
119
  def decrement(id, options = Options::Decrement::DEFAULT)
108
- resp = @backend.document_decrement(@collection.bucket_name, @collection.scope_name, @collection.name, id,
109
- options.to_backend)
110
- CounterResult.new do |res|
111
- res.cas = resp[:cas]
112
- res.content = resp[:content]
113
- res.mutation_token = @collection.send(:extract_mutation_token, resp)
120
+ @observability.record_operation(Observability::OP_DECREMENT, options.parent_span, self, :kv) do |obs_handler|
121
+ obs_handler.add_durability_level(options.durability_level)
122
+ resp = @backend.document_decrement(@collection.bucket_name, @collection.scope_name, @collection.name, id,
123
+ options.to_backend, obs_handler)
124
+ CounterResult.new do |res|
125
+ res.cas = resp[:cas]
126
+ res.content = resp[:content]
127
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
128
+ end
114
129
  end
115
130
  end
116
131
 
@@ -30,17 +30,20 @@ module Couchbase
30
30
  alias inspect to_s
31
31
 
32
32
  # @param [Couchbase::Backend] backend
33
- def initialize(backend, name)
33
+ #
34
+ # @api private
35
+ def initialize(backend, name, observability)
34
36
  backend.open_bucket(name, true)
35
37
  @backend = backend
36
38
  @name = name
39
+ @observability = observability
37
40
  end
38
41
 
39
42
  # Get default scope
40
43
  #
41
44
  # @return [Scope]
42
45
  def default_scope
43
- Scope.new(@backend, @name, "_default")
46
+ Scope.new(@backend, @name, "_default", @observability)
44
47
  end
45
48
 
46
49
  # Get a named scope
@@ -49,7 +52,7 @@ module Couchbase
49
52
  #
50
53
  # @return [Scope]
51
54
  def scope(scope_name)
52
- Scope.new(@backend, @name, scope_name)
55
+ Scope.new(@backend, @name, scope_name, @observability)
53
56
  end
54
57
 
55
58
  # Opens the named collection in the default scope of the bucket
@@ -65,7 +68,7 @@ module Couchbase
65
68
  #
66
69
  # @return [Collection]
67
70
  def default_collection
68
- Collection.new(@backend, @name, "_default", "_default")
71
+ Collection.new(@backend, @name, "_default", "_default", @observability)
69
72
  end
70
73
 
71
74
  # Performs query to view index.
@@ -82,18 +85,24 @@ module Couchbase
82
85
  # ))
83
86
  #
84
87
  # @return [ViewResult]
88
+ #
89
+ # @deprecated Views are deprecated in Couchbase Server 7.0+, and will be removed from a future server version.
90
+ # Views are not compatible with the Magma storage engine. Instead of views, use indexes and queries using the
91
+ # Index Service (GSI) and the Query Service (SQL++).
85
92
  def view_query(design_document_name, view_name, options = Options::View::DEFAULT)
86
- resp = @backend.document_view(@name, design_document_name, view_name, options.namespace, options.to_backend)
87
- ViewResult.new do |res|
88
- res.meta_data = ViewMetaData.new do |meta|
89
- meta.total_rows = resp[:meta][:total_rows]
90
- meta.debug_info = resp[:meta][:debug_info]
91
- end
92
- res.rows = resp[:rows].map do |entry|
93
- ViewRow.new do |row|
94
- row.id = entry[:id] if entry.key?(:id)
95
- row.key = JSON.parse(entry[:key])
96
- row.value = JSON.parse(entry[:value])
93
+ @observability.record_operation(Observability::OP_VIEW_QUERY, options.parent_span, self, :views) do |obs_handler|
94
+ resp = @backend.document_view(@name, design_document_name, view_name, options.namespace, options.to_backend, obs_handler)
95
+ ViewResult.new do |res|
96
+ res.meta_data = ViewMetaData.new do |meta|
97
+ meta.total_rows = resp[:meta][:total_rows]
98
+ meta.debug_info = resp[:meta][:debug_info]
99
+ end
100
+ res.rows = resp[:rows].map do |entry|
101
+ ViewRow.new do |row|
102
+ row.id = entry[:id] if entry.key?(:id)
103
+ row.key = JSON.parse(entry[:key])
104
+ row.value = JSON.parse(entry[:value])
105
+ end
97
106
  end
98
107
  end
99
108
  end
@@ -101,12 +110,16 @@ module Couchbase
101
110
 
102
111
  # @return [Management::CollectionManager]
103
112
  def collections
104
- Management::CollectionManager.new(@backend, @name)
113
+ Management::CollectionManager.new(@backend, @name, @observability)
105
114
  end
106
115
 
107
116
  # @return [Management::ViewIndexManager]
117
+ #
118
+ # @deprecated Views are deprecated in Couchbase Server 7.0+, and will be removed from a future server version.
119
+ # Views are not compatible with the Magma storage engine. Instead of views, use indexes and queries using the
120
+ # Index Service (GSI) and the Query Service (SQL++).
108
121
  def view_indexes
109
- Management::ViewIndexManager.new(@backend, @name)
122
+ Management::ViewIndexManager.new(@backend, @name, @observability)
110
123
  end
111
124
 
112
125
  # Performs application-level ping requests against services in the couchbase cluster
@@ -115,20 +128,22 @@ module Couchbase
115
128
  #
116
129
  # @return [PingResult]
117
130
  def ping(options = Options::Ping::DEFAULT)
118
- resp = @backend.ping(@name, options.to_backend)
119
- PingResult.new do |res|
120
- res.version = resp[:version]
121
- res.id = resp[:id]
122
- res.sdk = resp[:sdk]
123
- resp[:services].each do |type, svcs|
124
- res.services[type] = svcs.map do |svc|
125
- PingResult::ServiceInfo.new do |info|
126
- info.id = svc[:id]
127
- info.state = svc[:state]
128
- info.latency = svc[:latency]
129
- info.remote = svc[:remote]
130
- info.local = svc[:local]
131
- info.error = svc[:error]
131
+ @observability.record_operation(Observability::OP_PING, options.parent_span, self) do |_obs_handler|
132
+ resp = @backend.ping(@name, options.to_backend)
133
+ PingResult.new do |res|
134
+ res.version = resp[:version]
135
+ res.id = resp[:id]
136
+ res.sdk = resp[:sdk]
137
+ resp[:services].each do |type, svcs|
138
+ res.services[type] = svcs.map do |svc|
139
+ PingResult::ServiceInfo.new do |info|
140
+ info.id = svc[:id]
141
+ info.state = svc[:state]
142
+ info.latency = svc[:latency]
143
+ info.remote = svc[:remote]
144
+ info.local = svc[:local]
145
+ info.error = svc[:error]
146
+ end
132
147
  end
133
148
  end
134
149
  end
@@ -28,6 +28,12 @@ require "couchbase/analytics_options"
28
28
  require "couchbase/diagnostics"
29
29
 
30
30
  require "couchbase/protostellar"
31
+ require "couchbase/utils/observability"
32
+
33
+ require "couchbase/tracing/threshold_logging_tracer"
34
+ require "couchbase/tracing/noop_tracer"
35
+ require "couchbase/metrics/noop_meter"
36
+ require "couchbase/metrics/logging_meter"
31
37
 
32
38
  module Couchbase
33
39
  # The main entry point when connecting to a Couchbase cluster.
@@ -87,7 +93,39 @@ module Couchbase
87
93
  #
88
94
  # @return [Bucket]
89
95
  def bucket(name)
90
- Bucket.new(@backend, name)
96
+ Bucket.new(@backend, name, @observability)
97
+ end
98
+
99
+ # Updates the authenticator used for this cluster connection
100
+ #
101
+ # @param [PasswordAuthenticator, CertificateAuthenticator, JWTAuthenticator] authenticator the new authenticator
102
+ def update_authenticator(authenticator)
103
+ credentials = {}
104
+
105
+ case authenticator
106
+ when PasswordAuthenticator
107
+ credentials[:username] = authenticator.username
108
+ raise ArgumentError, "missing username" unless credentials[:username]
109
+
110
+ credentials[:password] = authenticator.password
111
+ raise ArgumentError, "missing password" unless credentials[:password]
112
+
113
+ when CertificateAuthenticator
114
+ credentials[:certificate_path] = authenticator.certificate_path
115
+ raise ArgumentError, "missing certificate path" unless credentials[:certificate_path]
116
+
117
+ credentials[:key_path] = authenticator.key_path
118
+ raise ArgumentError, "missing key path" unless credentials[:key_path]
119
+
120
+ when JWTAuthenticator
121
+ credentials[:jwt] = authenticator.token
122
+ raise ArgumentError, "missing token" unless credentials[:jwt]
123
+
124
+ else
125
+ raise ArgumentError, "argument must be an authenticator"
126
+ end
127
+
128
+ @backend.update_credentials(credentials)
91
129
  end
92
130
 
93
131
  # Performs a query against the query (N1QL) services
@@ -109,30 +147,34 @@ module Couchbase
109
147
  #
110
148
  # @return [QueryResult]
111
149
  def query(statement, options = Options::Query::DEFAULT)
112
- resp = @backend.document_query(statement, options.to_backend)
113
-
114
- QueryResult.new do |res|
115
- res.meta_data = QueryMetaData.new do |meta|
116
- meta.status = resp[:meta][:status]
117
- meta.request_id = resp[:meta][:request_id]
118
- meta.client_context_id = resp[:meta][:client_context_id]
119
- meta.signature = JSON.parse(resp[:meta][:signature]) if resp[:meta][:signature]
120
- meta.profile = JSON.parse(resp[:meta][:profile]) if resp[:meta][:profile]
121
- meta.metrics = QueryMetrics.new do |metrics|
122
- if resp[:meta][:metrics]
123
- metrics.elapsed_time = resp[:meta][:metrics][:elapsed_time]
124
- metrics.execution_time = resp[:meta][:metrics][:execution_time]
125
- metrics.sort_count = resp[:meta][:metrics][:sort_count]
126
- metrics.result_count = resp[:meta][:metrics][:result_count]
127
- metrics.result_size = resp[:meta][:metrics][:result_size]
128
- metrics.mutation_count = resp[:meta][:metrics][:mutation_count]
129
- metrics.error_count = resp[:meta][:metrics][:error_count]
130
- metrics.warning_count = resp[:meta][:metrics][:warning_count]
150
+ @observability.record_operation(Observability::OP_QUERY, options.parent_span, self, :query) do |obs_handler|
151
+ obs_handler.add_query_statement(statement, options)
152
+
153
+ resp = @backend.document_query(statement, options.to_backend, obs_handler)
154
+
155
+ QueryResult.new do |res|
156
+ res.meta_data = QueryMetaData.new do |meta|
157
+ meta.status = resp[:meta][:status]
158
+ meta.request_id = resp[:meta][:request_id]
159
+ meta.client_context_id = resp[:meta][:client_context_id]
160
+ meta.signature = JSON.parse(resp[:meta][:signature]) if resp[:meta][:signature]
161
+ meta.profile = JSON.parse(resp[:meta][:profile]) if resp[:meta][:profile]
162
+ meta.metrics = QueryMetrics.new do |metrics|
163
+ if resp[:meta][:metrics]
164
+ metrics.elapsed_time = resp[:meta][:metrics][:elapsed_time]
165
+ metrics.execution_time = resp[:meta][:metrics][:execution_time]
166
+ metrics.sort_count = resp[:meta][:metrics][:sort_count]
167
+ metrics.result_count = resp[:meta][:metrics][:result_count]
168
+ metrics.result_size = resp[:meta][:metrics][:result_size]
169
+ metrics.mutation_count = resp[:meta][:metrics][:mutation_count]
170
+ metrics.error_count = resp[:meta][:metrics][:error_count]
171
+ metrics.warning_count = resp[:meta][:metrics][:warning_count]
172
+ end
131
173
  end
174
+ meta.warnings = resp[:warnings].map { |warn| QueryWarning.new(warn[:code], warn[:message]) } if resp[:warnings]
132
175
  end
133
- meta.warnings = resp[:warnings].map { |warn| QueryWarning.new(warn[:code], warn[:message]) } if resp[:warnings]
176
+ res.instance_variable_set(:@rows, resp[:rows])
134
177
  end
135
- res.instance_variable_set(:@rows, resp[:rows])
136
178
  end
137
179
  end
138
180
 
@@ -147,30 +189,34 @@ module Couchbase
147
189
  #
148
190
  # @return [AnalyticsResult]
149
191
  def analytics_query(statement, options = Options::Analytics::DEFAULT)
150
- resp = @backend.document_analytics(statement, options.to_backend)
151
-
152
- AnalyticsResult.new do |res|
153
- res.transcoder = options.transcoder
154
- res.meta_data = AnalyticsMetaData.new do |meta|
155
- meta.status = resp[:meta][:status]
156
- meta.request_id = resp[:meta][:request_id]
157
- meta.client_context_id = resp[:meta][:client_context_id]
158
- meta.signature = JSON.parse(resp[:meta][:signature]) if resp[:meta][:signature]
159
- meta.profile = JSON.parse(resp[:meta][:profile]) if resp[:meta][:profile]
160
- meta.metrics = AnalyticsMetrics.new do |metrics|
161
- if resp[:meta][:metrics]
162
- metrics.elapsed_time = resp[:meta][:metrics][:elapsed_time]
163
- metrics.execution_time = resp[:meta][:metrics][:execution_time]
164
- metrics.result_count = resp[:meta][:metrics][:result_count]
165
- metrics.result_size = resp[:meta][:metrics][:result_size]
166
- metrics.error_count = resp[:meta][:metrics][:error_count]
167
- metrics.warning_count = resp[:meta][:metrics][:warning_count]
168
- metrics.processed_objects = resp[:meta][:metrics][:processed_objects]
192
+ @observability.record_operation(Observability::OP_ANALYTICS_QUERY, options.parent_span, self, :analytics) do |obs_handler|
193
+ obs_handler.add_query_statement(statement, options)
194
+
195
+ resp = @backend.document_analytics(statement, options.to_backend, obs_handler)
196
+
197
+ AnalyticsResult.new do |res|
198
+ res.transcoder = options.transcoder
199
+ res.meta_data = AnalyticsMetaData.new do |meta|
200
+ meta.status = resp[:meta][:status]
201
+ meta.request_id = resp[:meta][:request_id]
202
+ meta.client_context_id = resp[:meta][:client_context_id]
203
+ meta.signature = JSON.parse(resp[:meta][:signature]) if resp[:meta][:signature]
204
+ meta.profile = JSON.parse(resp[:meta][:profile]) if resp[:meta][:profile]
205
+ meta.metrics = AnalyticsMetrics.new do |metrics|
206
+ if resp[:meta][:metrics]
207
+ metrics.elapsed_time = resp[:meta][:metrics][:elapsed_time]
208
+ metrics.execution_time = resp[:meta][:metrics][:execution_time]
209
+ metrics.result_count = resp[:meta][:metrics][:result_count]
210
+ metrics.result_size = resp[:meta][:metrics][:result_size]
211
+ metrics.error_count = resp[:meta][:metrics][:error_count]
212
+ metrics.warning_count = resp[:meta][:metrics][:warning_count]
213
+ metrics.processed_objects = resp[:meta][:metrics][:processed_objects]
214
+ end
169
215
  end
216
+ res[:warnings] = resp[:warnings].map { |warn| AnalyticsWarning.new(warn[:code], warn[:message]) } if resp[:warnings]
170
217
  end
171
- res[:warnings] = resp[:warnings].map { |warn| AnalyticsWarning.new(warn[:code], warn[:message]) } if resp[:warnings]
218
+ res.instance_variable_set(:@rows, resp[:rows])
172
219
  end
173
- res.instance_variable_set(:@rows, resp[:rows])
174
220
  end
175
221
  end
176
222
 
@@ -191,8 +237,10 @@ module Couchbase
191
237
  #
192
238
  # @return [SearchResult]
193
239
  def search_query(index_name, query, options = Options::Search::DEFAULT)
194
- resp = @backend.document_search(nil, nil, index_name, JSON.generate(query), {}, options.to_backend)
195
- convert_search_result(resp, options)
240
+ @observability.record_operation(Observability::OP_SEARCH_QUERY, options.parent_span, self, :search) do |obs_handler|
241
+ resp = @backend.document_search(nil, nil, index_name, JSON.generate(query), {}, options.to_backend, obs_handler)
242
+ convert_search_result(resp, options)
243
+ end
196
244
  end
197
245
 
198
246
  # Performs a request against the Full Text Search (FTS) service.
@@ -203,34 +251,37 @@ module Couchbase
203
251
  #
204
252
  # @return [SearchResult]
205
253
  def search(index_name, search_request, options = Options::Search::DEFAULT)
206
- encoded_query, encoded_req = search_request.to_backend
207
- resp = @backend.document_search(nil, nil, index_name, encoded_query, encoded_req, options.to_backend(show_request: false))
208
- convert_search_result(resp, options)
254
+ @observability.record_operation(Observability::OP_SEARCH_QUERY, options.parent_span, self, :search) do |obs_handler|
255
+ encoded_query, encoded_req = search_request.to_backend
256
+ resp = @backend.document_search(nil, nil, index_name, encoded_query, encoded_req, options.to_backend(show_request: false),
257
+ obs_handler)
258
+ convert_search_result(resp, options)
259
+ end
209
260
  end
210
261
 
211
262
  # @return [Management::UserManager]
212
263
  def users
213
- Management::UserManager.new(@backend)
264
+ Management::UserManager.new(@backend, @observability)
214
265
  end
215
266
 
216
267
  # @return [Management::BucketManager]
217
268
  def buckets
218
- Management::BucketManager.new(@backend)
269
+ Management::BucketManager.new(@backend, @observability)
219
270
  end
220
271
 
221
272
  # @return [Management::QueryIndexManager]
222
273
  def query_indexes
223
- Management::QueryIndexManager.new(@backend)
274
+ Management::QueryIndexManager.new(@backend, @observability)
224
275
  end
225
276
 
226
277
  # @return [Management::AnalyticsIndexManager]
227
278
  def analytics_indexes
228
- Management::AnalyticsIndexManager.new(@backend)
279
+ Management::AnalyticsIndexManager.new(@backend, @observability)
229
280
  end
230
281
 
231
282
  # @return [Management::SearchIndexManager]
232
283
  def search_indexes
233
- Management::SearchIndexManager.new(@backend)
284
+ Management::SearchIndexManager.new(@backend, @observability)
234
285
  end
235
286
 
236
287
  # Closes all connections to services and free allocated resources
@@ -238,6 +289,7 @@ module Couchbase
238
289
  # @return [void]
239
290
  def disconnect
240
291
  @backend.close
292
+ @observability.close
241
293
  end
242
294
 
243
295
  # Creates diagnostic report that can be used to determine the health of the network connections.
@@ -332,24 +384,28 @@ module Couchbase
332
384
  raise ArgumentError, "missing username" unless credentials[:username]
333
385
  raise ArgumentError, "missing password" unless credentials[:password]
334
386
  when Options::Cluster
335
- open_options = options&.to_backend || {}
336
- authenticator = options&.authenticator
387
+ tracer = options.tracer
388
+ meter = options.meter
389
+ open_options = options.to_backend || {}
390
+ authenticator = options.authenticator
337
391
  case authenticator
338
392
  when PasswordAuthenticator
339
- credentials[:username] = authenticator&.username
393
+ credentials[:username] = authenticator.username
340
394
  raise ArgumentError, "missing username" unless credentials[:username]
341
395
 
342
- credentials[:password] = authenticator&.password
396
+ credentials[:password] = authenticator.password
343
397
  raise ArgumentError, "missing password" unless credentials[:password]
344
398
 
345
- open_options[:allowed_sasl_mechanisms] = authenticator&.allowed_sasl_mechanisms
399
+ open_options[:allowed_sasl_mechanisms] = authenticator.allowed_sasl_mechanisms
346
400
  when CertificateAuthenticator
347
- credentials[:certificate_path] = authenticator&.certificate_path
401
+ credentials[:certificate_path] = authenticator.certificate_path
348
402
  raise ArgumentError, "missing certificate path" unless credentials[:certificate_path]
349
403
 
350
- credentials[:key_path] = authenticator&.key_path
404
+ credentials[:key_path] = authenticator.key_path
351
405
  raise ArgumentError, "missing key path" unless credentials[:key_path]
352
-
406
+ when JWTAuthenticator
407
+ credentials[:jwt] = authenticator.token
408
+ raise ArgumentError, "missing token" unless credentials[:jwt]
353
409
  else
354
410
  raise ArgumentError, "options must have authenticator configured"
355
411
  end
@@ -359,6 +415,35 @@ module Couchbase
359
415
  end
360
416
 
361
417
  @backend = Backend.new
418
+
419
+ @observability = Observability::Wrapper.new(backend: @backend) do |w|
420
+ w.tracer = if !open_options[:enable_tracing].nil? && !open_options[:enable_tracing]
421
+ Tracing::NoopTracer.new
422
+ elsif tracer.nil?
423
+ Tracing::ThresholdLoggingTracer.new(
424
+ emit_interval: open_options[:threshold_emit_interval],
425
+ kv_threshold: open_options[:key_value_threshold],
426
+ query_threshold: open_options[:query_threshold],
427
+ views_threshold: open_options[:view_threshold],
428
+ search_threshold: open_options[:search_threshold],
429
+ analytics_threshold: open_options[:analytics_threshold],
430
+ management_threshold: open_options[:management_threshold],
431
+ sample_size: open_options[:threshold_sample_size],
432
+ )
433
+ else
434
+ tracer
435
+ end
436
+ w.meter = if !open_options[:enable_metrics].nil? && !open_options[:enable_metrics]
437
+ Metrics::NoopMeter.new
438
+ elsif meter.nil?
439
+ Metrics::LoggingMeter.new(
440
+ emit_interval: open_options[:metrics_emit_interval],
441
+ )
442
+ else
443
+ meter
444
+ end
445
+ end
446
+
362
447
  @backend.open(connection_string, credentials, open_options)
363
448
  end
364
449