couchbase 4.2.6-dev.1 → 4.2.6
Sign up to get free protection for your applications and to get access to all the features.
- package/CONTRIBUTING.md +97 -0
- package/deps/couchbase-cxx-client/core/io/dns_client.cxx +48 -10
- package/deps/couchbase-cxx-client/core/io/http_session.hxx +24 -1
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +22 -1
- package/deps/couchbase-cxx-client/core/logger/custom_rotating_file_sink.cxx +1 -1
- package/deps/couchbase-cxx-client/core/logger/logger.cxx +80 -20
- package/deps/couchbase-cxx-client/core/logger/logger.hxx +31 -0
- package/deps/couchbase-cxx-client/core/meta/features.hxx +6 -0
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.cxx +22 -1
- package/deps/couchbase-cxx-client/core/topology/capabilities.hxx +1 -0
- package/deps/couchbase-cxx-client/core/topology/capabilities_fmt.hxx +3 -0
- package/deps/couchbase-cxx-client/core/topology/configuration.hxx +5 -0
- package/deps/couchbase-cxx-client/core/topology/configuration_json.hxx +2 -0
- package/deps/couchbase-cxx-client/docs/cbc-analytics.md +3 -2
- package/deps/couchbase-cxx-client/docs/cbc-get.md +3 -2
- package/deps/couchbase-cxx-client/docs/cbc-pillowfight.md +3 -2
- package/deps/couchbase-cxx-client/docs/cbc-query.md +3 -2
- package/deps/couchbase-cxx-client/test/utils/logger.cxx +7 -0
- package/deps/couchbase-cxx-client/tools/utils.cxx +9 -2
- package/dist/binding.d.ts +2 -0
- package/dist/couchbase.d.ts +15 -0
- package/dist/couchbase.js +22 -1
- package/package.json +13 -13
- package/src/binding.cpp +28 -0
package/CONTRIBUTING.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
In addition to filing bugs, you may contribute by submitting patches to fix bugs in the library. Contributions may be submitted to <http://review.couchbase.com>. We use Gerrit as our code review system - and thus submitting a change requires an account there. While Github pull requests are not ignored, Gerrit pull requests will be responded to more quickly (and most likely with more detail).
|
4
|
+
|
5
|
+
For something to be accepted into the codebase, it must be formatted properly and have undergone proper testing.
|
6
|
+
|
7
|
+
## Branches and Tags
|
8
|
+
|
9
|
+
* The `master` branch represents the mainline branch. The master branch typically consists of content going into the next release.
|
10
|
+
* For older series of the Couchbase Node.js SDK see the corresponding branches: 2.x = `v2` and 3.x = `v3`.
|
11
|
+
|
12
|
+
## Contributing Patches
|
13
|
+
|
14
|
+
If you wish to contribute a new feature or a bug fix to the library, try to follow the following guidelines to help ensure your change gets merged upstream.
|
15
|
+
|
16
|
+
### Before you begin
|
17
|
+
|
18
|
+
For any code change, ensure the new code you write looks similar to the code surrounding it. We have no strict code style policies, but do request that your code stand out as little as possible from its surrounding neighborhood (unless of course your change is stylistic in nature).
|
19
|
+
|
20
|
+
If your change is going to involve a substantial amount of time or effort, please attempt to discuss it with the project developers first who will provide assistance and direction where possible.
|
21
|
+
|
22
|
+
#### For new features
|
23
|
+
|
24
|
+
Ensure the feature you are adding does not already exist, and think about how this feature may be useful for other users. In general less intrusive changes are more likely to be accepted.
|
25
|
+
|
26
|
+
#### For fixing bugs
|
27
|
+
|
28
|
+
Ensure the bug you are fixing is actually a bug (and not a usage) error, and that it has not been fixed in a more recent version. Please read the [release notes](https://docs.couchbase.com/nodejs-sdk/current/project-docs/sdk-release-notes.html) as well as the [issue tracker](https://issues.couchbase.com/projects/JSCBC/issues/) to see a list of open and resolved issues.
|
29
|
+
|
30
|
+
### Code Review
|
31
|
+
|
32
|
+
#### Signing up on Gerrit
|
33
|
+
|
34
|
+
Everything that is merged into the library goes through a code review process. The code review process is done via [Gerrit](http://review.couchbase.org).
|
35
|
+
|
36
|
+
To sign up for a Gerrit account, go to http://review.couchbase.org and click on the _Register_ link at the top right. Once you've signed in you will need to agree to the CLA (Contributor License Agreement) by going you your Gerrit account page and selecting the _Agreements_ link on the left. When you've done that, everything should flow through just fine. Be sure that you have registered your email address at http://review.couchbase.org/#/settings/contact as many sign-up methods won't pass emails along. Note that your email address in your code commit and in the Gerrit settings must match.
|
37
|
+
|
38
|
+
Add your public SSH key to Gerrit before submitting.
|
39
|
+
|
40
|
+
#### Setting up your fork with Gerrit
|
41
|
+
|
42
|
+
Assuming you have a repository created like so:
|
43
|
+
|
44
|
+
```
|
45
|
+
$ git clone https://github.com/couchbase/couchnode.git
|
46
|
+
```
|
47
|
+
|
48
|
+
you can simply perform two simple steps to get started with Gerrit:
|
49
|
+
|
50
|
+
```
|
51
|
+
$ git remote add gerrit ssh://${USERNAME}@review.couchbase.org:29418/couchnode
|
52
|
+
$ scp -P 29418 ${USERNAME}@review.couchbase.org:hooks/commit-msg .git/hooks
|
53
|
+
$ chmod a+x .git/hooks/commit-msg
|
54
|
+
```
|
55
|
+
|
56
|
+
The last change is required for annotating each commit message with a special header known as `Change-Id`. This allows Gerrit to group together different revisions of the same patch.
|
57
|
+
|
58
|
+
#### Pushing a changeset
|
59
|
+
|
60
|
+
Now that you have your change and a Gerrit account to push to, you need to upload the change for review. To do so, invoke the following incantation:
|
61
|
+
|
62
|
+
```
|
63
|
+
$ git push gerrit HEAD:refs/for/master
|
64
|
+
```
|
65
|
+
|
66
|
+
Where `gerrit` is the name of the _remote_ added earlier.
|
67
|
+
|
68
|
+
#### Pushing a new patchset
|
69
|
+
|
70
|
+
After a change has been pushed to Gerrit, further revisions can be made and then uploaded. These revisions are called patchsets and are associated with the the `Change-Id` created from the initial commit (see above). To push a new revision, simply ammend the commit (can also add the `--no-edit` option if no edits to the commit message are needed):
|
71
|
+
|
72
|
+
```
|
73
|
+
$ git commit --amend
|
74
|
+
```
|
75
|
+
|
76
|
+
Then push the revision to Gerrit:
|
77
|
+
|
78
|
+
```
|
79
|
+
$ git push gerrit HEAD:refs/for/master
|
80
|
+
```
|
81
|
+
|
82
|
+
Where `gerrit` is the name of the _remote_ added earlier.
|
83
|
+
|
84
|
+
#### Troubleshooting
|
85
|
+
|
86
|
+
You may encounter some errors when pushing. The most common are:
|
87
|
+
|
88
|
+
* "You are not authorized to push to this repository". You will get this if your account has not yet been approved. Please reach out in the [forums](https://www.couchbase.com/forums/c/node-js-sdk/12) if blocked.
|
89
|
+
* "Missing Change-Id". You need to install the `commit-msg` hook as described above. Note that even once you do this, you will need to ensure that any prior commits already have this header - this may be done by doing an interactive rebase (e.g. `git rebase -i origin/master` and selecting `reword` for all the commits; which will automatically fill in the Change-Id).
|
90
|
+
|
91
|
+
#### Reviewers
|
92
|
+
|
93
|
+
Once you've pushed your changeset you can add people to review. Currently these are:
|
94
|
+
|
95
|
+
* Jared Casey
|
96
|
+
* Matt Wozakowski
|
97
|
+
* Brett Lawson
|
@@ -72,16 +72,25 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
72
72
|
|
73
73
|
void execute(std::chrono::milliseconds total_timeout, std::chrono::milliseconds udp_timeout)
|
74
74
|
{
|
75
|
-
CB_LOG_TRACE("Query DNS-SRV (UDP) address=\"{}:{}\", udp_timeout={}, total_timeout={}
|
75
|
+
CB_LOG_TRACE("Query DNS-SRV (UDP) address=\"{}:{}\", udp_timeout={}, total_timeout={}",
|
76
76
|
address_.to_string(),
|
77
77
|
port_,
|
78
78
|
udp_timeout,
|
79
|
-
total_timeout
|
80
|
-
spdlog::to_hex(send_buf_));
|
79
|
+
total_timeout);
|
81
80
|
asio::ip::udp::endpoint endpoint(address_, port_);
|
82
81
|
udp_.open(endpoint.protocol());
|
82
|
+
CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
|
83
|
+
address_.to_string(),
|
84
|
+
port_,
|
85
|
+
send_buf_.size(),
|
86
|
+
spdlog::to_hex(send_buf_));
|
83
87
|
udp_.async_send_to(
|
84
|
-
asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t
|
88
|
+
asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t bytes_transferred1) mutable {
|
89
|
+
CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
|
90
|
+
self->address_.to_string(),
|
91
|
+
self->port_,
|
92
|
+
ec1 ? ec1.message() : "ok",
|
93
|
+
bytes_transferred1);
|
85
94
|
if (ec1) {
|
86
95
|
self->udp_deadline_.cancel();
|
87
96
|
CB_LOG_DEBUG("DNS UDP write operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
|
@@ -94,6 +103,13 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
94
103
|
self->recv_buf_.resize(512);
|
95
104
|
self->udp_.async_receive_from(
|
96
105
|
asio::buffer(self->recv_buf_), self->udp_sender_, [self](std::error_code ec2, std::size_t bytes_transferred) mutable {
|
106
|
+
CB_LOG_PROTOCOL("[DNS, UDP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
107
|
+
self->address_.to_string(),
|
108
|
+
self->port_,
|
109
|
+
ec2 ? ec2.message() : "ok",
|
110
|
+
bytes_transferred,
|
111
|
+
spdlog::to_hex(self->recv_buf_.data(), self->recv_buf_.data() + bytes_transferred));
|
112
|
+
|
97
113
|
self->udp_deadline_.cancel();
|
98
114
|
if (ec2) {
|
99
115
|
CB_LOG_DEBUG("DNS UDP read operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
|
@@ -168,10 +184,18 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
168
184
|
auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
|
169
185
|
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size & 0xffU));
|
170
186
|
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size >> 8U));
|
171
|
-
|
172
|
-
|
187
|
+
CB_LOG_PROTOCOL("[DNS, TCP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
|
188
|
+
self->address_.to_string(),
|
189
|
+
self->port_,
|
190
|
+
self->send_buf_.size(),
|
191
|
+
spdlog::to_hex(self->send_buf_));
|
173
192
|
asio::async_write(
|
174
|
-
self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t
|
193
|
+
self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t bytes_transferred2) mutable {
|
194
|
+
CB_LOG_PROTOCOL("[DNS, TCP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
|
195
|
+
self->address_.to_string(),
|
196
|
+
self->port_,
|
197
|
+
ec2 ? ec2.message() : "ok",
|
198
|
+
bytes_transferred2);
|
175
199
|
if (ec2) {
|
176
200
|
CB_LOG_DEBUG("DNS TCP write operation has been aborted, address=\"{}:{}\", ec={}",
|
177
201
|
self->address_.to_string(),
|
@@ -186,7 +210,14 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
186
210
|
asio::async_read(
|
187
211
|
self->tcp_,
|
188
212
|
asio::buffer(&self->recv_buf_size_, sizeof(std::uint16_t)),
|
189
|
-
[self](std::error_code ec3, std::size_t
|
213
|
+
[self](std::error_code ec3, std::size_t bytes_transferred3) mutable {
|
214
|
+
CB_LOG_PROTOCOL("[DNS, TCP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
215
|
+
self->address_.to_string(),
|
216
|
+
self->port_,
|
217
|
+
ec3 ? ec3.message() : "ok",
|
218
|
+
bytes_transferred3,
|
219
|
+
spdlog::to_hex(reinterpret_cast<std::uint8_t*>(&self->recv_buf_size_),
|
220
|
+
reinterpret_cast<std::uint8_t*>(&self->recv_buf_size_) + bytes_transferred3));
|
190
221
|
if (ec3) {
|
191
222
|
CB_LOG_DEBUG("DNS TCP buf size read operation has been aborted, address=\"{}:{}\", ec={}",
|
192
223
|
self->address_.to_string(),
|
@@ -199,8 +230,15 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
199
230
|
self->recv_buf_.resize(self->recv_buf_size_);
|
200
231
|
CB_LOG_DEBUG("DNS TCP schedule read of {} bytes", self->recv_buf_size_);
|
201
232
|
asio::async_read(
|
202
|
-
self->tcp_, asio::buffer(self->recv_buf_), [self](std::error_code ec4, std::size_t
|
233
|
+
self->tcp_, asio::buffer(self->recv_buf_), [self](std::error_code ec4, std::size_t bytes_transferred4) mutable {
|
203
234
|
self->deadline_.cancel();
|
235
|
+
CB_LOG_PROTOCOL("[DNS, TCP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
236
|
+
self->address_.to_string(),
|
237
|
+
self->port_,
|
238
|
+
ec4 ? ec4.message() : "ok",
|
239
|
+
bytes_transferred4,
|
240
|
+
spdlog::to_hex(self->recv_buf_.data(), self->recv_buf_.data() + bytes_transferred4));
|
241
|
+
|
204
242
|
if (ec4) {
|
205
243
|
CB_LOG_DEBUG("DNS TCP read operation has been aborted, address=\"{}:{}\", ec={}",
|
206
244
|
self->address_.to_string(),
|
@@ -208,7 +246,7 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
208
246
|
ec4.message());
|
209
247
|
return self->handler_({ ec4 });
|
210
248
|
}
|
211
|
-
self->recv_buf_.resize(
|
249
|
+
self->recv_buf_.resize(bytes_transferred4);
|
212
250
|
const dns_message message = dns_codec::decode(self->recv_buf_);
|
213
251
|
dns_srv_response resp{ ec4 };
|
214
252
|
resp.targets.reserve(message.answers.size());
|
@@ -31,7 +31,10 @@
|
|
31
31
|
|
32
32
|
#include <couchbase/error_codes.hxx>
|
33
33
|
|
34
|
+
#include <spdlog/fmt/bin_to_hex.h>
|
35
|
+
|
34
36
|
#include <asio.hpp>
|
37
|
+
|
35
38
|
#include <list>
|
36
39
|
#include <memory>
|
37
40
|
#include <utility>
|
@@ -448,7 +451,20 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
448
451
|
stream_->async_read_some(
|
449
452
|
asio::buffer(input_buffer_), [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
|
450
453
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
454
|
+
CB_LOG_PROTOCOL("[HTTP, IN] type={}, host=\"{}\", rc={}, bytes_received={}",
|
455
|
+
self->type_,
|
456
|
+
self->info_.remote_address(),
|
457
|
+
ec ? ec.message() : "ok",
|
458
|
+
bytes_transferred);
|
451
459
|
return;
|
460
|
+
} else {
|
461
|
+
CB_LOG_PROTOCOL("[HTTP, IN] type={}, host=\"{}\", rc={}, bytes_received={}{:a}",
|
462
|
+
self->type_,
|
463
|
+
self->info_.remote_address(),
|
464
|
+
ec ? ec.message() : "ok",
|
465
|
+
bytes_transferred,
|
466
|
+
spdlog::to_hex(self->input_buffer_.data(),
|
467
|
+
self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
|
452
468
|
}
|
453
469
|
self->last_active_ = std::chrono::steady_clock::now();
|
454
470
|
if (ec) {
|
@@ -495,9 +511,16 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
495
511
|
std::vector<asio::const_buffer> buffers;
|
496
512
|
buffers.reserve(writing_buffer_.size());
|
497
513
|
for (auto& buf : writing_buffer_) {
|
514
|
+
CB_LOG_PROTOCOL(
|
515
|
+
"[HTTP, OUT] type={}, host=\"{}\", buffer_size={}{:a}", type_, info_.remote_address(), buf.size(), spdlog::to_hex(buf));
|
498
516
|
buffers.emplace_back(asio::buffer(buf));
|
499
517
|
}
|
500
|
-
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t
|
518
|
+
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
|
519
|
+
CB_LOG_PROTOCOL("[HTTP, OUT] type={}, host=\"{}\", rc={}, bytes_sent={}",
|
520
|
+
self->type_,
|
521
|
+
self->info_.remote_address(),
|
522
|
+
ec ? ec.message() : "ok",
|
523
|
+
bytes_transferred);
|
501
524
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
502
525
|
return;
|
503
526
|
}
|
@@ -1365,7 +1365,20 @@ class mcbp_session_impl
|
|
1365
1365
|
asio::buffer(input_buffer_),
|
1366
1366
|
[self = shared_from_this(), stream_id = stream_->id()](std::error_code ec, std::size_t bytes_transferred) {
|
1367
1367
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
1368
|
+
CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}",
|
1369
|
+
self->endpoint_address_,
|
1370
|
+
self->endpoint_.port(),
|
1371
|
+
ec ? ec.message() : "ok",
|
1372
|
+
bytes_transferred);
|
1368
1373
|
return;
|
1374
|
+
} else {
|
1375
|
+
CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
1376
|
+
self->endpoint_address_,
|
1377
|
+
self->endpoint_.port(),
|
1378
|
+
ec ? ec.message() : "ok",
|
1379
|
+
bytes_transferred,
|
1380
|
+
spdlog::to_hex(self->input_buffer_.data(),
|
1381
|
+
self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
|
1369
1382
|
}
|
1370
1383
|
self->last_active_ = std::chrono::steady_clock::now();
|
1371
1384
|
if (ec) {
|
@@ -1433,13 +1446,21 @@ class mcbp_session_impl
|
|
1433
1446
|
std::vector<asio::const_buffer> buffers;
|
1434
1447
|
buffers.reserve(writing_buffer_.size());
|
1435
1448
|
for (auto& buf : writing_buffer_) {
|
1449
|
+
CB_LOG_PROTOCOL(
|
1450
|
+
"[MCBP, OUT] host=\"{}\", port={}, buffer_size={}{:a}", endpoint_address_, endpoint_.port(), buf.size(), spdlog::to_hex(buf));
|
1436
1451
|
buffers.emplace_back(asio::buffer(buf));
|
1437
1452
|
}
|
1438
|
-
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t
|
1453
|
+
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
|
1454
|
+
CB_LOG_PROTOCOL("[MCBP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
|
1455
|
+
self->endpoint_address_,
|
1456
|
+
self->endpoint_.port(),
|
1457
|
+
ec ? ec.message() : "ok",
|
1458
|
+
bytes_transferred);
|
1439
1459
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
1440
1460
|
return;
|
1441
1461
|
}
|
1442
1462
|
self->last_active_ = std::chrono::steady_clock::now();
|
1463
|
+
|
1443
1464
|
if (ec) {
|
1444
1465
|
CB_LOG_ERROR(R"({} IO error while writing to the socket("{}"): {} ({}))",
|
1445
1466
|
self->log_prefix_,
|
@@ -127,7 +127,7 @@ custom_rotating_file_sink<Mutex>::add_hook(const std::string& hook)
|
|
127
127
|
|
128
128
|
// Payload shouldn't contain anything yet, overwrite it
|
129
129
|
Expects(msg.payload.size() == 0);
|
130
|
-
msg.payload =
|
130
|
+
msg.payload = hookToAdd;
|
131
131
|
|
132
132
|
spdlog::memory_buf_t formatted;
|
133
133
|
formatter->format(msg, formatted);
|
@@ -22,7 +22,8 @@
|
|
22
22
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
23
23
|
#include <spdlog/spdlog.h>
|
24
24
|
|
25
|
-
static const std::string
|
25
|
+
static const std::string file_logger_name{ "couchbase_cxx_client_file_logger" };
|
26
|
+
static const std::string protocol_logger_name{ "couchbase_cxx_client_protocol_logger" };
|
26
27
|
|
27
28
|
/**
|
28
29
|
* Custom log pattern which the loggers will use.
|
@@ -39,7 +40,12 @@ static const std::string log_pattern{ "[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %oms, %
|
|
39
40
|
* messages and send them to the sinks, which do the actual writing (to file,
|
40
41
|
* to stream etc.) or further processing.
|
41
42
|
*/
|
42
|
-
static std::shared_ptr<spdlog::logger> file_logger;
|
43
|
+
static std::shared_ptr<spdlog::logger> file_logger{};
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Instance of the protocol logger.
|
47
|
+
*/
|
48
|
+
static std::shared_ptr<spdlog::logger> protocol_logger{};
|
43
49
|
|
44
50
|
namespace couchbase::core::logger
|
45
51
|
{
|
@@ -146,13 +152,11 @@ is_initialized()
|
|
146
152
|
return file_logger != nullptr;
|
147
153
|
}
|
148
154
|
|
149
|
-
|
150
|
-
|
151
|
-
* specified in a separate settings object.
|
152
|
-
*/
|
153
|
-
std::optional<std::string>
|
154
|
-
create_file_logger(const configuration& logger_settings)
|
155
|
+
std::pair<std::optional<std::string>, std::shared_ptr<spdlog::logger>>
|
156
|
+
create_file_logger_impl(const std::string logger_name, const configuration& logger_settings)
|
155
157
|
{
|
158
|
+
std::shared_ptr<spdlog::logger> logger{};
|
159
|
+
|
156
160
|
auto fname = logger_settings.filename;
|
157
161
|
auto buffersz = logger_settings.buffer_size;
|
158
162
|
auto cyclesz = logger_settings.cycle_size;
|
@@ -218,7 +222,7 @@ create_file_logger(const configuration& logger_settings)
|
|
218
222
|
spdlog::drop(logger_name);
|
219
223
|
|
220
224
|
if (logger_settings.unit_test) {
|
221
|
-
|
225
|
+
logger = std::make_shared<spdlog::logger>(logger_name, sink);
|
222
226
|
} else {
|
223
227
|
// Create the default thread pool for async logging
|
224
228
|
spdlog::init_thread_pool(buffersz, 1);
|
@@ -226,23 +230,71 @@ create_file_logger(const configuration& logger_settings)
|
|
226
230
|
// Get the thread pool so that we can actually construct the
|
227
231
|
// object with already created sinks...
|
228
232
|
auto tp = spdlog::thread_pool();
|
229
|
-
|
233
|
+
logger = std::make_shared<spdlog::async_logger>(logger_name, sink, tp, spdlog::async_overflow_policy::block);
|
230
234
|
}
|
231
235
|
|
232
|
-
|
233
|
-
|
236
|
+
logger->set_pattern(log_pattern);
|
237
|
+
logger->set_level(translate_level(logger_settings.log_level));
|
234
238
|
|
235
239
|
// Set the flushing interval policy
|
236
240
|
spdlog::flush_every(std::chrono::seconds(1));
|
237
241
|
|
238
|
-
spdlog::register_logger(
|
242
|
+
spdlog::register_logger(logger);
|
239
243
|
} catch (const spdlog::spdlog_ex& ex) {
|
240
244
|
std::string msg = std::string{ "Log initialization failed: " } + ex.what();
|
241
|
-
return
|
245
|
+
return { msg, {} };
|
246
|
+
}
|
247
|
+
return { {}, logger };
|
248
|
+
}
|
249
|
+
|
250
|
+
/**
|
251
|
+
* Initialises the loggers. Called if the logger configuration is
|
252
|
+
* specified in a separate settings object.
|
253
|
+
*/
|
254
|
+
std::optional<std::string>
|
255
|
+
create_file_logger(const configuration& logger_settings)
|
256
|
+
{
|
257
|
+
auto [error, logger] = create_file_logger_impl(file_logger_name, logger_settings);
|
258
|
+
if (error) {
|
259
|
+
return error;
|
260
|
+
}
|
261
|
+
file_logger = std::move(logger);
|
262
|
+
return {};
|
263
|
+
}
|
264
|
+
|
265
|
+
std::optional<std::string>
|
266
|
+
create_protocol_logger(const configuration& logger_settings)
|
267
|
+
{
|
268
|
+
if (logger_settings.filename.empty()) {
|
269
|
+
return "File name is missing";
|
270
|
+
}
|
271
|
+
auto config = logger_settings;
|
272
|
+
config.log_level = couchbase::core::logger::level::trace;
|
273
|
+
auto [error, logger] = create_file_logger_impl(protocol_logger_name, config);
|
274
|
+
if (error) {
|
275
|
+
return error;
|
242
276
|
}
|
277
|
+
protocol_logger = std::move(logger);
|
243
278
|
return {};
|
244
279
|
}
|
245
280
|
|
281
|
+
bool
|
282
|
+
should_log_protocol()
|
283
|
+
{
|
284
|
+
return protocol_logger != nullptr;
|
285
|
+
}
|
286
|
+
|
287
|
+
namespace detail
|
288
|
+
{
|
289
|
+
void
|
290
|
+
log_protocol(const char* file, int line, const char* function, std::string_view msg)
|
291
|
+
{
|
292
|
+
if (should_log_protocol()) {
|
293
|
+
return protocol_logger->log(spdlog::source_loc{ file, line, function }, spdlog::level::level_enum::trace, msg);
|
294
|
+
}
|
295
|
+
}
|
296
|
+
} // namespace detail
|
297
|
+
|
246
298
|
spdlog::logger*
|
247
299
|
get()
|
248
300
|
{
|
@@ -252,17 +304,20 @@ get()
|
|
252
304
|
void
|
253
305
|
reset()
|
254
306
|
{
|
255
|
-
spdlog::drop(
|
307
|
+
spdlog::drop(file_logger_name);
|
256
308
|
file_logger.reset();
|
309
|
+
|
310
|
+
spdlog::drop(protocol_logger_name);
|
311
|
+
protocol_logger.reset();
|
257
312
|
}
|
258
313
|
|
259
314
|
void
|
260
315
|
create_blackhole_logger()
|
261
316
|
{
|
262
317
|
// delete if already exists
|
263
|
-
spdlog::drop(
|
318
|
+
spdlog::drop(file_logger_name);
|
264
319
|
|
265
|
-
file_logger = std::make_shared<spdlog::logger>(
|
320
|
+
file_logger = std::make_shared<spdlog::logger>(file_logger_name, std::make_shared<spdlog::sinks::null_sink_mt>());
|
266
321
|
|
267
322
|
file_logger->set_level(spdlog::level::off);
|
268
323
|
file_logger->set_pattern(log_pattern);
|
@@ -274,11 +329,11 @@ void
|
|
274
329
|
create_console_logger()
|
275
330
|
{
|
276
331
|
// delete if already exists
|
277
|
-
spdlog::drop(
|
332
|
+
spdlog::drop(file_logger_name);
|
278
333
|
|
279
334
|
auto stderrsink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
|
280
335
|
|
281
|
-
file_logger = std::make_shared<spdlog::logger>(
|
336
|
+
file_logger = std::make_shared<spdlog::logger>(file_logger_name, stderrsink);
|
282
337
|
file_logger->set_level(spdlog::level::info);
|
283
338
|
file_logger->set_pattern(log_pattern);
|
284
339
|
|
@@ -322,8 +377,13 @@ void
|
|
322
377
|
set_log_levels(level lvl)
|
323
378
|
{
|
324
379
|
auto level = translate_level(lvl);
|
325
|
-
// Apply the function to each registered spdlog::logger
|
380
|
+
// Apply the function to each registered spdlog::logger except protocol logger
|
326
381
|
spdlog::apply_all([level](std::shared_ptr<spdlog::logger> l) {
|
382
|
+
if (l->name() == protocol_logger_name) {
|
383
|
+
l->set_level(spdlog::level::trace);
|
384
|
+
return;
|
385
|
+
}
|
386
|
+
|
327
387
|
try {
|
328
388
|
l->set_level(level);
|
329
389
|
} catch (const spdlog::spdlog_ex& e) {
|
@@ -54,6 +54,17 @@ level_from_str(const std::string& str);
|
|
54
54
|
std::optional<std::string>
|
55
55
|
create_file_logger(const configuration& logger_settings);
|
56
56
|
|
57
|
+
/**
|
58
|
+
* Protocol logger writes only communication logs with the nodes.
|
59
|
+
*
|
60
|
+
* It accepts the same settings as a file logger, and writes only to the filesystem.
|
61
|
+
*
|
62
|
+
* @param logger_settings
|
63
|
+
* @return
|
64
|
+
*/
|
65
|
+
std::optional<std::string>
|
66
|
+
create_protocol_logger(const configuration& logger_settings);
|
67
|
+
|
57
68
|
/**
|
58
69
|
* Initialize the logger with the blackhole logger object
|
59
70
|
*
|
@@ -144,6 +155,9 @@ set_log_levels(level lvl);
|
|
144
155
|
bool
|
145
156
|
should_log(level lvl);
|
146
157
|
|
158
|
+
bool
|
159
|
+
should_log_protocol();
|
160
|
+
|
147
161
|
namespace detail
|
148
162
|
{
|
149
163
|
/**
|
@@ -153,6 +167,9 @@ namespace detail
|
|
153
167
|
*/
|
154
168
|
void
|
155
169
|
log(const char* file, int line, const char* function, level lvl, std::string_view msg);
|
170
|
+
|
171
|
+
void
|
172
|
+
log_protocol(const char* file, int line, const char* function, std::string_view msg);
|
156
173
|
} // namespace detail
|
157
174
|
|
158
175
|
/**
|
@@ -168,6 +185,13 @@ log(const char* file, int line, const char* function, level lvl, const String& m
|
|
168
185
|
detail::log(file, line, function, lvl, fmt::format(msg, std::forward<Args>(args)...));
|
169
186
|
}
|
170
187
|
|
188
|
+
template<typename String, typename... Args>
|
189
|
+
inline void
|
190
|
+
log_protocol(const char* file, int line, const char* function, const String& msg, Args&&... args)
|
191
|
+
{
|
192
|
+
detail::log_protocol(file, line, function, fmt::format(msg, std::forward<Args>(args)...));
|
193
|
+
}
|
194
|
+
|
171
195
|
/**
|
172
196
|
* Tell the logger to flush its buffers
|
173
197
|
*/
|
@@ -214,6 +238,13 @@ is_initialized();
|
|
214
238
|
#define CB_LOG_CRITICAL(...) \
|
215
239
|
COUCHBASE_LOG(__FILE__, __LINE__, COUCHBASE_LOGGER_FUNCTION, couchbase::core::logger::level::critical, __VA_ARGS__)
|
216
240
|
|
241
|
+
#define CB_LOG_PROTOCOL(...) \
|
242
|
+
do { \
|
243
|
+
if (couchbase::core::logger::should_log_protocol()) { \
|
244
|
+
couchbase::core::logger::log_protocol(__FILE__, __LINE__, COUCHBASE_LOGGER_FUNCTION, __VA_ARGS__); \
|
245
|
+
} \
|
246
|
+
} while (false)
|
247
|
+
|
217
248
|
/**
|
218
249
|
* Convenience macros which log with the given level, and message, if the given
|
219
250
|
* level is currently enabled.
|
@@ -35,3 +35,9 @@
|
|
35
35
|
* passing TLS trust certificate by value
|
36
36
|
*/
|
37
37
|
#define COUCHBASE_CXX_CLIENT_CAN_PASS_TLS_TRUST_CERTIFICATE_BY_VALUE 1
|
38
|
+
|
39
|
+
/**
|
40
|
+
* Range scan is available in the core
|
41
|
+
* couchbase::core::range_scan_orchestrator and relevant options in the core API
|
42
|
+
*/
|
43
|
+
#define COUCHBASE_CXX_CLIENT_CORE_HAS_RANGE_SCAN 1
|
@@ -412,13 +412,33 @@ class range_scan_orchestrator_impl
|
|
412
412
|
return tl::unexpected(errc::common::invalid_argument);
|
413
413
|
}
|
414
414
|
|
415
|
+
// Get the collection ID before starting any of the streams
|
416
|
+
{
|
417
|
+
auto barrier = std::make_shared<std::promise<tl::expected<get_collection_id_result, std::error_code>>>();
|
418
|
+
auto f = barrier->get_future();
|
419
|
+
get_collection_id_options const get_cid_options{ options_.retry_strategy, options_.timeout, options_.parent_span };
|
420
|
+
agent_.get_collection_id(scope_name_, collection_name_, get_cid_options, [barrier](auto result, auto ec) {
|
421
|
+
if (ec) {
|
422
|
+
return barrier->set_value(tl::unexpected(ec));
|
423
|
+
}
|
424
|
+
barrier->set_value(result);
|
425
|
+
});
|
426
|
+
auto get_cid_res = f.get();
|
427
|
+
if (!get_cid_res.has_value()) {
|
428
|
+
return tl::unexpected(get_cid_res.error());
|
429
|
+
}
|
430
|
+
collection_id_ = get_cid_res->collection_id;
|
431
|
+
}
|
432
|
+
|
415
433
|
auto batch_time_limit = std::chrono::duration_cast<std::chrono::milliseconds>(0.9 * options_.timeout);
|
416
434
|
range_scan_continue_options const continue_options{
|
417
435
|
options_.batch_item_limit, options_.batch_byte_limit, batch_time_limit, options_.timeout, options_.retry_strategy,
|
418
436
|
};
|
419
437
|
for (std::uint16_t vbucket = 0; vbucket < gsl::narrow_cast<std::uint16_t>(vbucket_map_.size()); ++vbucket) {
|
420
438
|
const range_scan_create_options create_options{
|
421
|
-
scope_name_,
|
439
|
+
scope_name_, {},
|
440
|
+
scan_type_, options_.timeout,
|
441
|
+
collection_id_, vbucket_to_snapshot_requirements_[vbucket],
|
422
442
|
options_.ids_only, options_.retry_strategy,
|
423
443
|
};
|
424
444
|
|
@@ -653,6 +673,7 @@ class range_scan_orchestrator_impl
|
|
653
673
|
topology::configuration::vbucket_map vbucket_map_;
|
654
674
|
std::string scope_name_;
|
655
675
|
std::string collection_name_;
|
676
|
+
std::uint32_t collection_id_;
|
656
677
|
std::variant<std::monostate, range_scan, prefix_scan, sampling_scan> scan_type_;
|
657
678
|
range_scan_orchestrator_options options_;
|
658
679
|
std::map<std::size_t, std::optional<range_snapshot_requirements>> vbucket_to_snapshot_requirements_;
|
@@ -67,6 +67,9 @@ struct fmt::formatter<couchbase::core::bucket_capability> {
|
|
67
67
|
case couchbase::core::bucket_capability::tombstoned_user_xattrs:
|
68
68
|
name = "tombstoned_user_xattrs";
|
69
69
|
break;
|
70
|
+
case couchbase::core::bucket_capability::range_scan:
|
71
|
+
name = "range_scan";
|
72
|
+
break;
|
70
73
|
}
|
71
74
|
return format_to(ctx.out(), "{}", name);
|
72
75
|
}
|
@@ -117,6 +117,11 @@ struct configuration {
|
|
117
117
|
return cluster_capabilities.find(cluster_capability::n1ql_read_from_replica) != cluster_capabilities.end();
|
118
118
|
}
|
119
119
|
|
120
|
+
[[nodiscard]] bool supports_range_scan() const
|
121
|
+
{
|
122
|
+
return bucket_capabilities.find(bucket_capability::range_scan) != bucket_capabilities.end();
|
123
|
+
}
|
124
|
+
|
120
125
|
[[nodiscard]] bool ephemeral() const
|
121
126
|
{
|
122
127
|
// Use bucket capabilities to identify if couchapi is missing (then its ephemeral). If its null then
|
@@ -233,6 +233,8 @@ struct traits<couchbase::core::topology::configuration> {
|
|
233
233
|
result.bucket_capabilities.insert(couchbase::core::bucket_capability::nodes_ext);
|
234
234
|
} else if (name == "xattr") {
|
235
235
|
result.bucket_capabilities.insert(couchbase::core::bucket_capability::xattr);
|
236
|
+
} else if (name == "rangeScan") {
|
237
|
+
result.bucket_capabilities.insert(couchbase::core::bucket_capability::range_scan);
|
236
238
|
}
|
237
239
|
}
|
238
240
|
}
|
@@ -34,8 +34,9 @@ Execute one or more Analytics queries and print results to standard output.
|
|
34
34
|
### LOGGER OPTIONS
|
35
35
|
|
36
36
|
<dl>
|
37
|
-
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]
|
38
|
-
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR)
|
37
|
+
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]</dd>
|
38
|
+
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR).</dd>
|
39
|
+
<dt>`--log-protocol=PATH`</dt><dd>File to send protocol logs.</dd>
|
39
40
|
</dl>
|
40
41
|
|
41
42
|
### CONNECTION OPTIONS
|
@@ -34,8 +34,9 @@ Retrieve one or more documents from the server and print them to standard output
|
|
34
34
|
### LOGGER OPTIONS
|
35
35
|
|
36
36
|
<dl>
|
37
|
-
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]
|
38
|
-
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR)
|
37
|
+
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]</dd>
|
38
|
+
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR).</dd>
|
39
|
+
<dt>`--log-protocol=PATH`</dt><dd>File to send protocol logs.</dd>
|
39
40
|
</dl>
|
40
41
|
|
41
42
|
### CONNECTION OPTIONS
|
@@ -41,8 +41,9 @@ Run simple workload generator that sends GET/UPSERT requests with optional N1QL
|
|
41
41
|
### LOGGER OPTIONS
|
42
42
|
|
43
43
|
<dl>
|
44
|
-
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]
|
45
|
-
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR)
|
44
|
+
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]</dd>
|
45
|
+
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR).</dd>
|
46
|
+
<dt>`--log-protocol=PATH`</dt><dd>File to send protocol logs.</dd>
|
46
47
|
</dl>
|
47
48
|
|
48
49
|
### CONNECTION OPTIONS
|
@@ -42,8 +42,9 @@ Execute one or more N1QL queries and print results to standard output.
|
|
42
42
|
### LOGGER OPTIONS
|
43
43
|
|
44
44
|
<dl>
|
45
|
-
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]
|
46
|
-
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR)
|
45
|
+
<dt>`--log-level=LEVEL`</dt><dd>Log level (allowed values are: `trace`, `debug`, `info`, `warning`, `error`, `critical`, `off`). [default: `off`]</dd>
|
46
|
+
<dt>`--log-output=PATH`</dt><dd>File to send logs (when is not set, logs will be written to STDERR).</dd>
|
47
|
+
<dt>`--log-protocol=PATH`</dt><dd>File to send protocol logs.</dd>
|
47
48
|
</dl>
|
48
49
|
|
49
50
|
### CONNECTION OPTIONS
|
@@ -16,6 +16,7 @@
|
|
16
16
|
*/
|
17
17
|
|
18
18
|
#include "core/logger/logger.hxx"
|
19
|
+
#include "core/logger/configuration.hxx"
|
19
20
|
|
20
21
|
#include <spdlog/details/os.h>
|
21
22
|
#include <spdlog/spdlog.h>
|
@@ -32,9 +33,15 @@ init_logger()
|
|
32
33
|
if (auto env_val = spdlog::details::os::getenv("TEST_LOG_LEVEL"); !env_val.empty()) {
|
33
34
|
couchbase::core::logger::set_log_levels(couchbase::core::logger::level_from_str(env_val));
|
34
35
|
}
|
36
|
+
if (auto env_val = spdlog::details::os::getenv("TEST_LOG_PROTOCOL"); !env_val.empty()) {
|
37
|
+
couchbase::core::logger::configuration configuration{};
|
38
|
+
configuration.filename = env_val;
|
39
|
+
couchbase::core::logger::create_protocol_logger(configuration);
|
40
|
+
}
|
35
41
|
if (auto env_val = spdlog::details::os::getenv("TEST_LOG_INCLUDE_LOCATION"); !env_val.empty()) {
|
36
42
|
spdlog::set_pattern("[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %oms, %v at %@ %!");
|
37
43
|
}
|
44
|
+
|
38
45
|
initialized = true;
|
39
46
|
}
|
40
47
|
}
|
@@ -367,8 +367,9 @@ usage_block_for_logger() -> std::string
|
|
367
367
|
|
368
368
|
return fmt::format(R"(
|
369
369
|
Logger options:
|
370
|
-
--log-level=LEVEL
|
371
|
-
--log-output=PATH
|
370
|
+
--log-level=LEVEL Log level (allowed values are: {allowed_levels}). CBC_LOG_LEVEL. [default: {log_level}]
|
371
|
+
--log-output=PATH File to send logs (when is not set, logs will be written to STDERR).
|
372
|
+
--log-protocol=PATH File to send protocol logs.
|
372
373
|
)",
|
373
374
|
fmt::arg("allowed_levels", fmt::join(allowed_log_levels, ", ")),
|
374
375
|
fmt::arg("log_level", default_log_level()));
|
@@ -393,6 +394,12 @@ apply_logger_options(const docopt::Options& options)
|
|
393
394
|
couchbase::core::logger::create_file_logger(configuration);
|
394
395
|
}
|
395
396
|
|
397
|
+
if (options.find("--log-protocol") != options.end() && options.at("--log-protocol")) {
|
398
|
+
couchbase::core::logger::configuration configuration{};
|
399
|
+
configuration.filename = options.at("--log-protocol").asString();
|
400
|
+
couchbase::core::logger::create_protocol_logger(configuration);
|
401
|
+
}
|
402
|
+
|
396
403
|
spdlog::set_level(spdlog::level::from_str(log_level));
|
397
404
|
couchbase::core::logger::set_log_levels(level);
|
398
405
|
}
|
package/dist/binding.d.ts
CHANGED
@@ -2671,6 +2671,8 @@ export interface CppTransaction {
|
|
2671
2671
|
export interface CppBinding extends CppBindingAutogen {
|
2672
2672
|
cbppVersion: string;
|
2673
2673
|
cbppMetadata: string;
|
2674
|
+
enableProtocolLogger: (filename: string) => void;
|
2675
|
+
shutdownLogger: () => void;
|
2674
2676
|
Connection: {
|
2675
2677
|
new (): CppConnection;
|
2676
2678
|
};
|
package/dist/couchbase.d.ts
CHANGED
@@ -23,6 +23,21 @@ export declare const lcbVersion: string;
|
|
23
23
|
*/
|
24
24
|
export declare const cbppVersion: string;
|
25
25
|
export declare const cbppMetadata: string;
|
26
|
+
/**
|
27
|
+
* Volatile: This API is subject to change at any time.
|
28
|
+
*
|
29
|
+
* Exposes the underlying couchbase++ library protocol logger. This method is for
|
30
|
+
* logging/debugging purposes and must be used with caution as network details will
|
31
|
+
* be logged to the provided file.
|
32
|
+
*/
|
33
|
+
export declare function enableProtocolLoggerToSaveNetworkTrafficToFile(filename: string): void;
|
34
|
+
/**
|
35
|
+
* Volatile: This API is subject to change at any time.
|
36
|
+
*
|
37
|
+
* Shutdowns the underlying couchbase++ logger.
|
38
|
+
*
|
39
|
+
*/
|
40
|
+
export declare function shutdownLogger(): void;
|
26
41
|
export * from './analyticsindexmanager';
|
27
42
|
export * from './analyticstypes';
|
28
43
|
export * from './authenticators';
|
package/dist/couchbase.js
CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
18
|
};
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
-
exports.cbppMetadata = exports.cbppVersion = exports.lcbVersion = exports.connect = void 0;
|
20
|
+
exports.shutdownLogger = exports.enableProtocolLoggerToSaveNetworkTrafficToFile = exports.cbppMetadata = exports.cbppVersion = exports.lcbVersion = exports.connect = void 0;
|
21
21
|
const binding_1 = __importDefault(require("./binding"));
|
22
22
|
const cluster_1 = require("./cluster");
|
23
23
|
/**
|
@@ -46,6 +46,27 @@ exports.lcbVersion = binding_1.default.cbppVersion;
|
|
46
46
|
*/
|
47
47
|
exports.cbppVersion = binding_1.default.cbppVersion;
|
48
48
|
exports.cbppMetadata = binding_1.default.cbppMetadata;
|
49
|
+
/**
|
50
|
+
* Volatile: This API is subject to change at any time.
|
51
|
+
*
|
52
|
+
* Exposes the underlying couchbase++ library protocol logger. This method is for
|
53
|
+
* logging/debugging purposes and must be used with caution as network details will
|
54
|
+
* be logged to the provided file.
|
55
|
+
*/
|
56
|
+
function enableProtocolLoggerToSaveNetworkTrafficToFile(filename) {
|
57
|
+
binding_1.default.enableProtocolLogger(filename);
|
58
|
+
}
|
59
|
+
exports.enableProtocolLoggerToSaveNetworkTrafficToFile = enableProtocolLoggerToSaveNetworkTrafficToFile;
|
60
|
+
/**
|
61
|
+
* Volatile: This API is subject to change at any time.
|
62
|
+
*
|
63
|
+
* Shutdowns the underlying couchbase++ logger.
|
64
|
+
*
|
65
|
+
*/
|
66
|
+
function shutdownLogger() {
|
67
|
+
binding_1.default.shutdownLogger();
|
68
|
+
}
|
69
|
+
exports.shutdownLogger = shutdownLogger;
|
49
70
|
__exportStar(require("./analyticsindexmanager"), exports);
|
50
71
|
__exportStar(require("./analyticstypes"), exports);
|
51
72
|
__exportStar(require("./authenticators"), exports);
|
package/package.json
CHANGED
@@ -55,7 +55,7 @@
|
|
55
55
|
"type": "git",
|
56
56
|
"url": "http://github.com/couchbase/couchnode.git"
|
57
57
|
},
|
58
|
-
"version": "4.2.6
|
58
|
+
"version": "4.2.6",
|
59
59
|
"config": {
|
60
60
|
"native": false
|
61
61
|
},
|
@@ -80,17 +80,17 @@
|
|
80
80
|
]
|
81
81
|
},
|
82
82
|
"optionalDependencies": {
|
83
|
-
"@couchbase/couchbase-darwin-arm64-openssl1": "4.2.6
|
84
|
-
"@couchbase/couchbase-darwin-arm64-openssl3": "4.2.6
|
85
|
-
"@couchbase/couchbase-darwin-x64-openssl1": "4.2.6
|
86
|
-
"@couchbase/couchbase-darwin-x64-openssl3": "4.2.6
|
87
|
-
"@couchbase/couchbase-linux-arm64-openssl1": "4.2.6
|
88
|
-
"@couchbase/couchbase-linux-arm64-openssl3": "4.2.6
|
89
|
-
"@couchbase/couchbase-linux-x64-openssl1": "4.2.6
|
90
|
-
"@couchbase/couchbase-linux-x64-openssl3": "4.2.6
|
91
|
-
"@couchbase/couchbase-linuxmusl-x64-openssl1": "4.2.6
|
92
|
-
"@couchbase/couchbase-linuxmusl-x64-openssl3": "4.2.6
|
93
|
-
"@couchbase/couchbase-win32-x64-openssl1": "4.2.6
|
94
|
-
"@couchbase/couchbase-win32-x64-openssl3": "4.2.6
|
83
|
+
"@couchbase/couchbase-darwin-arm64-openssl1": "4.2.6",
|
84
|
+
"@couchbase/couchbase-darwin-arm64-openssl3": "4.2.6",
|
85
|
+
"@couchbase/couchbase-darwin-x64-openssl1": "4.2.6",
|
86
|
+
"@couchbase/couchbase-darwin-x64-openssl3": "4.2.6",
|
87
|
+
"@couchbase/couchbase-linux-arm64-openssl1": "4.2.6",
|
88
|
+
"@couchbase/couchbase-linux-arm64-openssl3": "4.2.6",
|
89
|
+
"@couchbase/couchbase-linux-x64-openssl1": "4.2.6",
|
90
|
+
"@couchbase/couchbase-linux-x64-openssl3": "4.2.6",
|
91
|
+
"@couchbase/couchbase-linuxmusl-x64-openssl1": "4.2.6",
|
92
|
+
"@couchbase/couchbase-linuxmusl-x64-openssl3": "4.2.6",
|
93
|
+
"@couchbase/couchbase-win32-x64-openssl1": "4.2.6",
|
94
|
+
"@couchbase/couchbase-win32-x64-openssl3": "4.2.6"
|
95
95
|
}
|
96
96
|
}
|
package/src/binding.cpp
CHANGED
@@ -6,12 +6,36 @@
|
|
6
6
|
#include "scan_iterator.hpp"
|
7
7
|
#include "transaction.hpp"
|
8
8
|
#include "transactions.hpp"
|
9
|
+
#include <core/logger/configuration.hxx>
|
9
10
|
#include <napi.h>
|
10
11
|
#include <spdlog/spdlog.h>
|
11
12
|
|
12
13
|
namespace couchnode
|
13
14
|
{
|
14
15
|
|
16
|
+
Napi::Value enable_protocol_logger(const Napi::CallbackInfo &info)
|
17
|
+
{
|
18
|
+
try {
|
19
|
+
auto filename = info[0].ToString().Utf8Value();
|
20
|
+
couchbase::core::logger::configuration configuration{};
|
21
|
+
configuration.filename = filename;
|
22
|
+
couchbase::core::logger::create_protocol_logger(configuration);
|
23
|
+
} catch (...) {
|
24
|
+
return Napi::Error::New(info.Env(), "Unexpected C++ error").Value();
|
25
|
+
}
|
26
|
+
return info.Env().Null();
|
27
|
+
}
|
28
|
+
|
29
|
+
Napi::Value shutdown_logger(const Napi::CallbackInfo &info)
|
30
|
+
{
|
31
|
+
try {
|
32
|
+
couchbase::core::logger::shutdown();
|
33
|
+
} catch (...) {
|
34
|
+
return Napi::Error::New(info.Env(), "Unexpected C++ error").Value();
|
35
|
+
}
|
36
|
+
return info.Env().Null();
|
37
|
+
}
|
38
|
+
|
15
39
|
Napi::Object Init(Napi::Env env, Napi::Object exports)
|
16
40
|
{
|
17
41
|
spdlog::set_pattern("[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %oms, %v");
|
@@ -63,6 +87,10 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
|
|
63
87
|
exports.Set(
|
64
88
|
Napi::String::New(env, "cbppMetadata"),
|
65
89
|
Napi::String::New(env, couchbase::core::meta::sdk_build_info_json()));
|
90
|
+
exports.Set(Napi::String::New(env, "enableProtocolLogger"),
|
91
|
+
Napi::Function::New<enable_protocol_logger>(env));
|
92
|
+
exports.Set(Napi::String::New(env, "shutdownLogger"),
|
93
|
+
Napi::Function::New<shutdown_logger>(env));
|
66
94
|
return exports;
|
67
95
|
}
|
68
96
|
|