Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6059981
Working on v20.19.7
marco-ippolito Nov 25, 2025
97fc9b0
deps: update undici to 6.23.0
mcollina Jan 5, 2026
85f73e7
tls: route callback exceptions through error handlers
mcollina Dec 22, 2025
1febc48
lib: add TLSSocket default error handler
RafaelGSS Oct 31, 2025
14fbbb5
lib: disable futimes when permission model is enabled
RafaelGSS Oct 21, 2025
494f62d
lib,permission: require full read and write to symlink APIs
RafaelGSS Nov 10, 2025
8f9ba3f
deps: update c-ares to v1.34.6
nodejs-github-bot Dec 11, 2025
d7a5c58
src: rethrow stack overflow exceptions in async_hooks
mcollina Dec 9, 2025
51f4de4
src,lib: refactor unsafe buffer creation to remove zero-fill toggle
ChALkeR Nov 7, 2025
1f7186e
2026-01-13, Version 20.20.0 'Iron' (LTS)
marco-ippolito Jan 7, 2026
2a6ecd0
deps: update libcurl to 8.17.0
santigimeno Nov 11, 2025
d573042
deps: update to protobuf v33.0
santigimeno Nov 11, 2025
02a5752
deps: update grpc to 1.76.0
santigimeno Nov 11, 2025
4da827c
deps: update to protobuf v33.2
santigimeno Dec 9, 2025
6208f51
test: add grpc tests testing TLS connections
santigimeno Jan 6, 2026
8b66ac0
agents: add option to dump grpc keylog file
santigimeno Jan 6, 2026
a97f1ef
lib,src: set default metrics interval to 5 secs
santigimeno Jan 13, 2026
1e3c606
agents: increase gRPC timeout from 10 to 60 secs
santigimeno Jan 13, 2026
d9346a8
agents: fix otel-cpp warning when setting creds
santigimeno Jan 13, 2026
794bb0d
src: fix null pointer deref error in SetWeak cb
santigimeno Jan 14, 2026
f372694
Merge tag 'v20.20.0' into node-v20.20.0-nsolid-v6.2.0-release
santigimeno Jan 14, 2026
4240296
deps: fix windows linking error for grpc
santigimeno Jan 14, 2026
090e2d4
test: fix test addons compilation
santigimeno Jan 15, 2026
2981454
2026-01-14, Version 20.20.0-nsolid-v6.2.0 'Iron'
santigimeno Jan 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ release.
</tr>
<tr>
<td valign="top">
<b><a href="doc/changelogs/CHANGELOG_V20.md#20.19.6">20.19.6</a></b><br/>
<b><a href="doc/changelogs/CHANGELOG_V20.md#20.20.0">20.20.0</a></b><br/>
<a href="doc/changelogs/CHANGELOG_V20.md#20.19.6">20.19.6</a><br/>
<a href="doc/changelogs/CHANGELOG_V20.md#20.19.5">20.19.5</a><br/>
<a href="doc/changelogs/CHANGELOG_V20.md#20.19.4">20.19.4</a><br/>
<a href="doc/changelogs/CHANGELOG_V20.md#20.19.3">20.19.3</a><br/>
Expand Down
54 changes: 31 additions & 23 deletions agents/grpc/src/grpc_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h"
#include "opentelemetry/exporters/otlp/otlp_metric_utils.h"

using std::chrono::duration_cast;
using std::chrono::nanoseconds;
using std::chrono::seconds;
using std::chrono::system_clock;
using std::chrono::time_point;
using google::protobuf::Arena;
Expand Down Expand Up @@ -64,6 +67,7 @@ constexpr size_t span_msg_q_min_size = 1000;

const char* const kNSOLID_GRPC_INSECURE = "NSOLID_GRPC_INSECURE";
const char* const kNSOLID_GRPC_CERTS = "NSOLID_GRPC_CERTS";
const char* const kNSOLID_GRPC_KEYLOG = "NSOLID_GRPC_KEYLOG";

const int MAX_AUTH_RETRIES = 20;
const uint64_t auth_timer_interval = 500;
Expand All @@ -73,16 +77,14 @@ const size_t GRPC_MAX_SIZE = 4L * 1024 * 1024; // 4GB
const int PUB_KEY_SIZE = 40;
const int CONSOLE_ID_SIZE = 36;

const seconds DEFAULT_GRPC_TIMEOUT = seconds{ 60 };

JSThreadMetrics::JSThreadMetrics(SharedEnvInst envinst):
metrics_(ThreadMetrics::Create(envinst)) {
}

std::pair<int64_t, int64_t>
create_recorded(const time_point<system_clock>& ts) {
using std::chrono::duration_cast;
using std::chrono::seconds;
using std::chrono::nanoseconds;

system_clock::duration dur = ts.time_since_epoch();
return { duration_cast<seconds>(dur).count(),
duration_cast<nanoseconds>(dur % seconds(1)).count() };
Expand Down Expand Up @@ -457,6 +459,17 @@ GrpcAgent::GrpcAgent(): hooks_init_(false),
cacert_ += "\n";
}
}

std::string keylog;
if (per_process::system_environment->Get(kNSOLID_GRPC_KEYLOG).To(&keylog)) {
if (!keylog.empty() && keylog != "0") {
tls_keylog_file_ = "./nsolid-tls-keylog-" +
std::to_string(uv_os_getpid()) + ".log";
uv_fs_t req;
uv_fs_unlink(nullptr, &req, tls_keylog_file_.c_str(), nullptr);
uv_fs_req_cleanup(&req);
}
}
}

GrpcAgent::~GrpcAgent() {
Expand Down Expand Up @@ -1037,6 +1050,7 @@ int GrpcAgent::config(const json& config) {
opts.endpoint = endpoint;
opts.metadata = {{"nsolid-agent-id", agent_id_},
{"nsolid-saas", saas()}};
opts.timeout = DEFAULT_GRPC_TIMEOUT;
// Make sure the client is initialized. We set it to the same
// default value as ax_concurrent_requests as the exporters.
opts.max_concurrent_requests = 64;
Expand All @@ -1049,11 +1063,17 @@ int GrpcAgent::config(const json& config) {
}
}

nsolid_service_stub_ = GrpcClient::MakeNSolidServiceStub(opts);
nsolid_service_stub_ =
GrpcClient::MakeNSolidServiceStub(opts, tls_keylog_file_);

// CommandStream needs to be created before the OTLP client to avoid
// a race condition with abseil mutexes.
reset_command_stream();

// Enable TLS keylog for the OTLP client
opts.credentials = GrpcClient::MakeCredentials(opts, tls_keylog_file_);
opts.use_ssl_credentials = false;

std::shared_ptr<OtlpGrpcClient> client =
OtlpGrpcClientFactory::Create(opts);

Expand All @@ -1063,13 +1083,9 @@ int GrpcAgent::config(const json& config) {
options.endpoint = endpoint;
options.metadata = {{"nsolid-agent-id", agent_id_},
{"nsolid-saas", saas()}};
options.timeout = DEFAULT_GRPC_TIMEOUT;
if (!insecure) {
options.use_ssl_credentials = true;
if (!custom_certs_.empty()) {
options.ssl_credentials_cacert_as_string = custom_certs_;
} else {
options.ssl_credentials_cacert_as_string = cacert_;
}
options.credentials = opts.credentials;
}

trace_exporter_ = std::make_unique<OtlpGrpcExporter>(options, client);
Expand All @@ -1080,13 +1096,9 @@ int GrpcAgent::config(const json& config) {
options.endpoint = endpoint;
options.metadata = {{"nsolid-agent-id", agent_id_},
{"nsolid-saas", saas()}};
options.timeout = DEFAULT_GRPC_TIMEOUT;
if (!insecure) {
options.use_ssl_credentials = true;
if (!custom_certs_.empty()) {
options.ssl_credentials_cacert_as_string = custom_certs_;
} else {
options.ssl_credentials_cacert_as_string = cacert_;
}
options.credentials = opts.credentials;
}

metrics_exporter_ =
Expand All @@ -1098,13 +1110,9 @@ int GrpcAgent::config(const json& config) {
options.endpoint = endpoint;
options.metadata = {{"nsolid-agent-id", agent_id_},
{"nsolid-saas", saas()}};
options.timeout = DEFAULT_GRPC_TIMEOUT;
if (!insecure) {
options.use_ssl_credentials = true;
if (!custom_certs_.empty()) {
options.ssl_credentials_cacert_as_string = custom_certs_;
} else {
options.ssl_credentials_cacert_as_string = cacert_;
}
options.credentials = opts.credentials;
}

log_exporter_ =
Expand Down
1 change: 1 addition & 0 deletions agents/grpc/src/grpc_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ class GrpcAgent: public std::enable_shared_from_this<GrpcAgent>,
std::unique_ptr<CommandStream> command_stream_;
std::string cacert_;
std::string custom_certs_;
std::string tls_keylog_file_;

// For the gRPC server
nsuv::ns_async command_msg_;
Expand Down
78 changes: 54 additions & 24 deletions agents/grpc/src/grpc_client.cc
Original file line number Diff line number Diff line change
@@ -1,26 +1,66 @@
#include "grpc_client.h"
#include "debug_utils-inl.h"
#include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h"
#include <grpcpp/security/tls_credentials_options.h>

using grpc::Channel;
using grpc::ChannelArguments;
using grpc::ClientContext;
using grpc::CreateCustomChannel;
using grpc::InsecureChannelCredentials;
using grpc::SslCredentials;
using grpc::SslCredentialsOptions;
using ::grpc::Channel;
using ::grpc::ChannelArguments;
using ::grpc::ClientContext;
using ::grpc::CreateCustomChannel;
using ::grpc::InsecureChannelCredentials;
using ::grpc::SslCredentials;
using ::grpc::SslCredentialsOptions;
// The following experimental gRPC TLS APIs are required for TLS session key
// logging (via set_tls_session_key_log_file_path), which is not currently
// supported by the stable SslCredentials API.
// These APIs are subject to change in future gRPC releases. This project
// currently pins gRPC to version 1.76.0
// (see deps/grpc/include/grpcpp/version_info.h).
using ::grpc::experimental::IdentityKeyCertPair;
using ::grpc::experimental::TlsCredentials;
using ::grpc::experimental::TlsChannelCredentialsOptions;
using ::grpc::experimental::StaticDataCertificateProvider;
using grpcagent::NSolidService;
using opentelemetry::v1::exporter::otlp::OtlpGrpcClientOptions;

namespace node {
namespace nsolid {
namespace grpc {

/**
* Create gRPC channel credentials.
*/
std::shared_ptr<::grpc::ChannelCredentials>
GrpcClient::MakeCredentials(const OtlpGrpcClientOptions& options,
const std::string& tls_keylog_file) {
if (!options.use_ssl_credentials) {
return InsecureChannelCredentials();
}

if (!tls_keylog_file.empty()) {
TlsChannelCredentialsOptions tls_opts;
if (!options.ssl_credentials_cacert_as_string.empty()) {
auto cert_provider = std::make_shared<StaticDataCertificateProvider>(
options.ssl_credentials_cacert_as_string,
std::vector<IdentityKeyCertPair>());
tls_opts.set_certificate_provider(cert_provider);
tls_opts.watch_root_certs();
}
tls_opts.set_tls_session_key_log_file_path(tls_keylog_file);
return TlsCredentials(tls_opts);
}

SslCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = options.ssl_credentials_cacert_as_string;
return SslCredentials(ssl_opts);
}

/**
* Create gRPC channel.
*/
std::shared_ptr<Channel>
GrpcClient::MakeChannel(const OtlpGrpcClientOptions& options) {
GrpcClient::MakeChannel(const OtlpGrpcClientOptions& options,
const std::string& tls_keylog_file) {
std::shared_ptr<Channel> channel;
ChannelArguments grpc_arguments;
// Configure the keepalive of the Client Channel. The keepalive time period is
Expand All @@ -32,21 +72,10 @@ std::shared_ptr<Channel>
grpc_arguments.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 15 * 1000 /* 15 sec*/);
grpc_arguments.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1);
grpc_arguments.SetInt(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 0);
if (!options.use_ssl_credentials) {
channel = CreateCustomChannel(options.endpoint,
InsecureChannelCredentials(),
grpc_arguments);
return channel;
}


SslCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = options.ssl_credentials_cacert_as_string;
auto channel_creds = SslCredentials(ssl_opts);
channel = CreateCustomChannel(options.endpoint,
channel_creds,
grpc_arguments);
return channel;
return CreateCustomChannel(options.endpoint,
MakeCredentials(options, tls_keylog_file),
grpc_arguments);
}

/**
Expand All @@ -68,8 +97,9 @@ GrpcClient::MakeClientContext(const std::string& agent_id,
* Create N|Solid service stub to communicate with the N|Solid Console.
*/
std::unique_ptr<NSolidService::StubInterface>
GrpcClient::MakeNSolidServiceStub(const OtlpGrpcClientOptions& options) {
return NSolidService::NewStub(MakeChannel(options));
GrpcClient::MakeNSolidServiceStub(const OtlpGrpcClientOptions& options,
const std::string& tls_keylog_file) {
return NSolidService::NewStub(MakeChannel(options, tls_keylog_file));
}

} // namespace grpc
Expand Down
13 changes: 11 additions & 2 deletions agents/grpc/src/grpc_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,15 @@ class GrpcClient {
* Create gRPC channel.
*/
static std::shared_ptr<::grpc::Channel>
MakeChannel(const OtlpGrpcClientOptions& options);
MakeChannel(const OtlpGrpcClientOptions& options,
const std::string& tls_keylog_file = "");

/**
* Create gRPC channel credentials.
*/
static std::shared_ptr<::grpc::ChannelCredentials>
MakeCredentials(const OtlpGrpcClientOptions& options,
const std::string& tls_keylog_file);

/**
* Create gRPC client context to call RPC.
Expand All @@ -72,7 +80,8 @@ class GrpcClient {
* Create N|Solid service stub to communicate with the N|Solid Console.
*/
static std::unique_ptr<grpcagent::NSolidService::StubInterface>
MakeNSolidServiceStub(const OtlpGrpcClientOptions& options);
MakeNSolidServiceStub(const OtlpGrpcClientOptions& options,
const std::string& tls_keylog_file);

/**
* Generic DelegateAsyncExport for any event type.
Expand Down
Loading
Loading