Skip to content

Commit 4d4f8ea

Browse files
committed
agents: add nsolid-version and add it to metadata
Also, cache the metadata so it's not generated multiple times per different rpc's. Finally, resolve having both `nsolid-saas` and `nsolid-saas-token` header name and settle for the first.
1 parent f397c0b commit 4d4f8ea

11 files changed

Lines changed: 89 additions & 54 deletions

File tree

agents/grpc/src/asset_stream.cc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,11 @@ AssetStream::AssetStream(
1717
NSolidService::StubInterface* stub,
1818
AssetStor&& stor,
1919
std::weak_ptr<AssetStreamObserver> observer,
20-
const std::string& agent_id,
21-
const std::string& saas,
20+
const GrpcMetadata& metadata,
2221
AssetStreamRpcType rpc_type): observer_(observer),
2322
stor_(std::move(stor)) {
2423
ASSERT_EQ(0, lock_.init(true));
25-
context_.AddMetadata("nsolid-agent-id", agent_id);
26-
if (!saas.empty()) {
27-
context_.AddMetadata("nsolid-saas-token", saas);
28-
}
24+
GrpcClient::AddMetadata(&context_, metadata);
2925

3026
// Call the appropriate RPC method based on the rpc_type parameter
3127
if (rpc_type == EXPORT_CONTINUOUS_PROFILE) {

agents/grpc/src/asset_stream.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define AGENTS_GRPC_SRC_ASSET_STREAM_H_
33

44
#include "./proto/nsolid_service.grpc.pb.h"
5+
#include "grpc_client.h"
56
#include "grpcpp/grpcpp.h"
67
#include "nsolid/thread_safe.h"
78
#include "../../src/profile_collector.h"
@@ -54,8 +55,7 @@ class AssetStream: public ::grpc::ClientWriteReactor<grpcagent::Asset> {
5455
explicit AssetStream(grpcagent::NSolidService::StubInterface* stub,
5556
AssetStor&& stor,
5657
std::weak_ptr<AssetStreamObserver> observer,
57-
const std::string& agent_id,
58-
const std::string& saas,
58+
const GrpcMetadata& metadata,
5959
AssetStreamRpcType rpc_type = EXPORT_ASSET);
6060

6161
~AssetStream();

agents/grpc/src/command_stream.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,11 @@ namespace grpc {
1212

1313
CommandStream::CommandStream(NSolidService::StubInterface* stub,
1414
std::weak_ptr<CommandStreamObserver> observer,
15-
const std::string& agent_id,
16-
const std::string& saas): observer_(observer) {
15+
const GrpcMetadata& metadata):
16+
observer_(observer) {
1717
ASSERT_EQ(0, lock_.init(true));
1818
ASSERT_EQ(0, uv_cond_init(&on_done_cond_));
19-
context_.AddMetadata("nsolid-agent-id", agent_id);
20-
if (!saas.empty()) {
21-
context_.AddMetadata("nsolid-saas-token", saas);
22-
}
19+
GrpcClient::AddMetadata(&context_, metadata);
2320
context_.set_wait_for_ready(true);
2421
stub->async()->Command(&context_, this);
2522
StartRead(&server_request_);

agents/grpc/src/command_stream.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define AGENTS_GRPC_SRC_COMMAND_STREAM_H_
33

44
#include "./proto/nsolid_service.grpc.pb.h"
5+
#include "grpc_client.h"
56
#include "grpcpp/grpcpp.h"
67
#include "nsolid/thread_safe.h"
78
#include "nsuv-inl.h"
@@ -31,8 +32,7 @@ class CommandStream:
3132
public:
3233
explicit CommandStream(grpcagent::NSolidService::StubInterface* stub,
3334
std::weak_ptr<CommandStreamObserver> observer,
34-
const std::string& agent_id,
35-
const std::string& saas);
35+
const GrpcMetadata& metadata);
3636

3737
~CommandStream();
3838

agents/grpc/src/grpc_agent.cc

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h"
2222
#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h"
2323
#include "opentelemetry/exporters/otlp/otlp_metric_utils.h"
24+
#include "../../src/node_version.h"
2425

2526
using std::chrono::duration_cast;
2627
using std::chrono::nanoseconds;
@@ -122,6 +123,23 @@ ErrorType translate_error(int err) {
122123
}
123124
}
124125

126+
GrpcMetadata GrpcAgent::BuildRpcMetadata(const std::string& agent_id,
127+
const std::string& saas) {
128+
GrpcMetadata metadata = {
129+
{"nsolid-agent-id", agent_id},
130+
{"nsolid-version", NSOLID_VERSION_STRING},
131+
};
132+
if (!saas.empty()) {
133+
metadata.emplace("nsolid-saas", saas);
134+
}
135+
136+
return metadata;
137+
}
138+
139+
void GrpcAgent::RefreshRpcMetadata() {
140+
rpc_metadata_ = BuildRpcMetadata(agent_id_, saas());
141+
}
142+
125143
void PopulateCommon(grpcagent::CommonResponse* common,
126144
const std::string& command,
127145
const char* req_id) {
@@ -431,6 +449,7 @@ GrpcAgent::GrpcAgent(): hooks_init_(false),
431449
proc_prev_stor_(),
432450
config_(json::object()),
433451
agent_id_(GetAgentId()),
452+
rpc_metadata_(BuildRpcMetadata(agent_id_, "")),
434453
auth_retries_(0),
435454
unauthorized_(false),
436455
assets_enabled_(true),
@@ -501,8 +520,7 @@ void GrpcAgent::reset_command_stream() {
501520
Debug("Resetting command stream\n");
502521
command_stream_ = std::make_unique<CommandStream>(nsolid_service_stub_.get(),
503522
weak_from_this(),
504-
agent_id_,
505-
saas());
523+
rpc_metadata());
506524
}
507525

508526
void GrpcAgent::set_asset_cb(SharedEnvInst envinst,
@@ -1018,21 +1036,24 @@ int GrpcAgent::config(const json& config) {
10181036
json old_config = config_;
10191037
config_ = config;
10201038
json diff = json::diff(old_config, config_);
1039+
const bool saas_changed = utils::find_any_fields_in_diff(diff, { "/saas" });
1040+
const bool grpc_changed = utils::find_any_fields_in_diff(diff, { "/grpc" });
10211041
DebugJSON("Old Config: \n%s\n", old_config);
10221042
DebugJSON("NewConfig: \n%s\n", config_);
10231043
DebugJSON("Diff: \n%s\n", diff);
10241044

1025-
if (utils::find_any_fields_in_diff(diff, { "/saas" })) {
1045+
if (saas_changed) {
10261046
auto it = config_.find("saas");
10271047
saas_.reset();
10281048
if (it != config_.end()) {
10291049
parse_saas_token(*it);
10301050
}
1051+
RefreshRpcMetadata();
10311052
}
10321053

1033-
if (utils::find_any_fields_in_diff(diff, { "/grpc" })) {
1054+
if (grpc_changed || saas_changed) {
10341055
auto it = config_.find("grpc");
1035-
if (it != config_.end()) {
1056+
if (it != config_.end() || saas_) {
10361057
// Setup the client/s
10371058

10381059
bool insecure = false;
@@ -1053,8 +1074,7 @@ int GrpcAgent::config(const json& config) {
10531074
OtlpGrpcClientOptions opts;
10541075
opts.compression = "gzip";
10551076
opts.endpoint = endpoint;
1056-
opts.metadata = {{"nsolid-agent-id", agent_id_},
1057-
{"nsolid-saas", saas()}};
1077+
opts.metadata = rpc_metadata();
10581078
opts.timeout = DEFAULT_GRPC_TIMEOUT;
10591079
// Make sure the client is initialized. We set it to the same
10601080
// default value as ax_concurrent_requests as the exporters.
@@ -1086,8 +1106,7 @@ int GrpcAgent::config(const json& config) {
10861106
OtlpGrpcExporterOptions options;
10871107
options.compression = "gzip";
10881108
options.endpoint = endpoint;
1089-
options.metadata = {{"nsolid-agent-id", agent_id_},
1090-
{"nsolid-saas", saas()}};
1109+
options.metadata = rpc_metadata();
10911110
options.timeout = DEFAULT_GRPC_TIMEOUT;
10921111
if (!insecure) {
10931112
options.credentials = opts.credentials;
@@ -1099,8 +1118,7 @@ int GrpcAgent::config(const json& config) {
10991118
OtlpGrpcMetricExporterOptions options;
11001119
options.compression = "gzip";
11011120
options.endpoint = endpoint;
1102-
options.metadata = {{"nsolid-agent-id", agent_id_},
1103-
{"nsolid-saas", saas()}};
1121+
options.metadata = rpc_metadata();
11041122
options.timeout = DEFAULT_GRPC_TIMEOUT;
11051123
if (!insecure) {
11061124
options.credentials = opts.credentials;
@@ -1113,8 +1131,7 @@ int GrpcAgent::config(const json& config) {
11131131
OtlpGrpcLogRecordExporterOptions options;
11141132
options.compression = "gzip";
11151133
options.endpoint = endpoint;
1116-
options.metadata = {{"nsolid-agent-id", agent_id_},
1117-
{"nsolid-saas", saas()}};
1134+
options.metadata = rpc_metadata();
11181135
options.timeout = DEFAULT_GRPC_TIMEOUT;
11191136
if (!insecure) {
11201137
options.credentials = opts.credentials;
@@ -1534,8 +1551,7 @@ void GrpcAgent::got_continuous_profile(
15341551
AssetStream* stream = new AssetStream(nsolid_service_stub_.get(),
15351552
AssetStor{stor.type, thread_id},
15361553
weak_from_this(),
1537-
agent_id_,
1538-
saas(),
1554+
rpc_metadata(),
15391555
EXPORT_CONTINUOUS_PROFILE);
15401556
it = cont_profile_stor_map_.emplace(thread_id, ProfileStor{
15411557
utils::generate_unique_id(),
@@ -1794,7 +1810,7 @@ void GrpcAgent::send_blocked_loop_event(BlockedLoopStor&& stor) {
17941810
Arena::Create<grpcagent::BlockedLoopEvent>(arena.get());
17951811
PopulateBlockedLoopEvent(event, stor);
17961812

1797-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
1813+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
17981814

17991815
GrpcClient::DelegateAsyncExport<grpcagent::BlockedLoopEvent>(
18001816
nsolid_service_stub_.get(),
@@ -1831,7 +1847,7 @@ void GrpcAgent::send_exit() {
18311847
exit_body->set_profile(cpu_profile_state.last_main_profile);
18321848
}
18331849

1834-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
1850+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
18351851
uv_cond_t cond;
18361852
uv_mutex_t lock;
18371853
bool signaled = false;
@@ -1881,7 +1897,7 @@ void GrpcAgent::send_info_event(const char* req_id) {
18811897
PopulateInfoEvent(info_event, info, req_id);
18821898
}
18831899

1884-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
1900+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
18851901

18861902
GrpcClient::DelegateAsyncExport<grpcagent::InfoEvent>(
18871903
nsolid_service_stub_.get(),
@@ -1909,7 +1925,7 @@ void GrpcAgent::send_metrics_event(const char* req_id) {
19091925
thr_metrics_cache_,
19101926
req_id);
19111927

1912-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
1928+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
19131929

19141930
GrpcClient::DelegateAsyncExport<grpcagent::MetricsEvent>(
19151931
nsolid_service_stub_.get(),
@@ -1932,7 +1948,7 @@ void GrpcAgent::send_packages_event(const char* req_id) {
19321948
auto packages_event = Arena::Create<grpcagent::PackagesEvent>(arena.get());
19331949
PopulatePackagesEvent(packages_event, req_id);
19341950

1935-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
1951+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
19361952

19371953
GrpcClient::DelegateAsyncExport<grpcagent::PackagesEvent>(
19381954
nsolid_service_stub_.get(),
@@ -1956,7 +1972,7 @@ void GrpcAgent::send_reconfigure_event(const char* req_id) {
19561972
Arena::Create<grpcagent::ReconfigureEvent>(arena.get());
19571973
PopulateReconfigureEvent(reconfigure_event, req_id);
19581974

1959-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
1975+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
19601976

19611977
GrpcClient::DelegateAsyncExport<grpcagent::ReconfigureEvent>(
19621978
nsolid_service_stub_.get(),
@@ -2007,7 +2023,7 @@ void GrpcAgent::send_source_code_event(const grpcagent::CommandRequest& req) {
20072023
}
20082024
}
20092025

2010-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
2026+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
20112027

20122028
GrpcClient::DelegateAsyncExport<grpcagent::SourceCodeEvent>(
20132029
nsolid_service_stub_.get(),
@@ -2030,7 +2046,7 @@ void GrpcAgent::send_startup_times_event(const char* req_id) {
20302046
auto st_event = Arena::Create<grpcagent::StartupTimesEvent>(arena.get());
20312047
PopulateStartupTimesEvent(st_event, req_id);
20322048

2033-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
2049+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
20342050

20352051
GrpcClient::DelegateAsyncExport<grpcagent::StartupTimesEvent>(
20362052
nsolid_service_stub_.get(),
@@ -2055,7 +2071,7 @@ void GrpcAgent::send_unblocked_loop_event(BlockedLoopStor&& stor) {
20552071
Arena::Create<grpcagent::UnblockedLoopEvent>(arena.get());
20562072
PopulateUnblockedLoopEvent(event, stor);
20572073

2058-
auto context = GrpcClient::MakeClientContext(agent_id_, saas());
2074+
auto context = GrpcClient::MakeClientContext(rpc_metadata());
20592075

20602076
GrpcClient::DelegateAsyncExport<grpcagent::UnblockedLoopEvent>(
20612077
nsolid_service_stub_.get(),
@@ -2170,8 +2186,7 @@ ErrorType GrpcAgent::do_start_prof_end(ErrorType err,
21702186
auto stream = new AssetStream(nsolid_service_stub_.get(),
21712187
AssetStor{type, thread_id},
21722188
weak_from_this(),
2173-
agent_id_,
2174-
saas(),
2189+
rpc_metadata(),
21752190
EXPORT_ASSET);
21762191
if (err != ErrorType::ESuccess) {
21772192
send_asset_error(type, req_id, std::move(opts), stream, err);

agents/grpc/src/grpc_agent.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class GrpcAgent: public std::enable_shared_from_this<GrpcAgent>,
110110
return saas_ ? saas_->token : empty;
111111
}
112112

113+
const GrpcMetadata& rpc_metadata() const { return rpc_metadata_; }
114+
113115
private:
114116
struct CommandRequestStor {
115117
grpcagent::CommandRequest request;
@@ -256,6 +258,11 @@ class GrpcAgent: public std::enable_shared_from_this<GrpcAgent>,
256258

257259
void parse_saas_token(const std::string& token);
258260

261+
static GrpcMetadata BuildRpcMetadata(const std::string& agent_id,
262+
const std::string& saas);
263+
264+
void RefreshRpcMetadata();
265+
259266
bool pending_profiles() const;
260267

261268
void reconfigure(const grpcagent::CommandRequest& config);
@@ -335,6 +342,7 @@ class GrpcAgent: public std::enable_shared_from_this<GrpcAgent>,
335342
TSQueue<nlohmann::json> config_msg_q_;
336343
nlohmann::json config_;
337344
std::string agent_id_;
345+
GrpcMetadata rpc_metadata_;
338346
std::unique_ptr<SaaSInfo> saas_;
339347

340348
nsuv::ns_timer auth_timer_;

agents/grpc/src/grpc_client.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,20 @@ std::shared_ptr<Channel>
8282
* Create gRPC client context to call RPC.
8383
*/
8484
std::unique_ptr<ClientContext>
85-
GrpcClient::MakeClientContext(const std::string& agent_id,
86-
const std::string& saas) {
85+
GrpcClient::MakeClientContext(const GrpcMetadata& metadata) {
8786
std::unique_ptr<ClientContext> context = std::make_unique<ClientContext>();
88-
context->AddMetadata("nsolid-agent-id", agent_id);
89-
if (!saas.empty()) {
90-
context->AddMetadata("nsolid-saas-token", saas);
91-
}
87+
AddMetadata(context.get(), metadata);
9288

9389
return context;
9490
}
9591

92+
void GrpcClient::AddMetadata(ClientContext* context,
93+
const GrpcMetadata& metadata) {
94+
for (const auto& [key, value] : metadata) {
95+
context->AddMetadata(key, value);
96+
}
97+
}
98+
9699
/**
97100
* Create N|Solid service stub to communicate with the N|Solid Console.
98101
*/

agents/grpc/src/grpc_client.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "google/protobuf/util/json_util.h"
1010
#include "grpc_utils.h"
1111
#include "grpcpp/grpcpp.h"
12+
#include "opentelemetry/exporters/otlp/otlp_environment.h"
1213
#include "opentelemetry/version.h"
1314

1415
OPENTELEMETRY_BEGIN_NAMESPACE
@@ -21,6 +22,7 @@ OPENTELEMETRY_END_NAMESPACE
2122

2223
using google::protobuf::Arena;
2324
using opentelemetry::v1::exporter::otlp::OtlpGrpcClientOptions;
25+
using GrpcMetadata = opentelemetry::v1::exporter::otlp::OtlpHeaders;
2426

2527
namespace node {
2628
namespace nsolid {
@@ -74,7 +76,10 @@ class GrpcClient {
7476
* Create gRPC client context to call RPC.
7577
*/
7678
static std::unique_ptr<::grpc::ClientContext>
77-
MakeClientContext(const std::string& agent_id, const std::string& saas);
79+
MakeClientContext(const GrpcMetadata& metadata);
80+
81+
static void AddMetadata(::grpc::ClientContext* context,
82+
const GrpcMetadata& metadata);
7883

7984
/**
8085
* Create N|Solid service stub to communicate with the N|Solid Console.

test/agents/test-grpc-basic.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import fixtures from '../common/fixtures.js';
44
import assert from 'node:assert';
55
import {
66
checkExitData,
7+
checkRpcMetadata,
78
GRPCServer,
89
TestClient,
910
} from '../common/nsolid-grpc-agent/index.js';
@@ -165,8 +166,12 @@ tests.push({
165166
config.saas = correctEnv.NSOLID_SAAS;
166167
}
167168

168-
grpcServer.on('command', mustCall(async ({ agentId }) => {
169+
grpcServer.on('command', mustCall(async ({ agentId, metadata }) => {
169170
// Verify the CommandStream is working by sending a command from server to client
171+
checkRpcMetadata(metadata, agentId);
172+
if (correctEnv.NSOLID_SAAS) {
173+
assert.strictEqual(metadata['nsolid-saas'][0], correctEnv.NSOLID_SAAS);
174+
}
170175
const infoResult = await grpcServer.info(agentId);
171176
assert.ok(infoResult);
172177
const exit = await child.shutdown(0);

0 commit comments

Comments
 (0)