Skip to content

Commit f2faf54

Browse files
committed
Allow user use custom grpc::ChannelArguments
1 parent 37a57da commit f2faf54

4 files changed

Lines changed: 120 additions & 39 deletions

File tree

exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ class OtlpGrpcClient
254254
bool IsShutdown() const noexcept;
255255

256256
private:
257+
friend class OtlpGrpcClientTestPeer;
258+
259+
// Build gRPC channel arguments from exporter options. Shared by MakeChannel() and unit tests.
260+
static grpc::ChannelArguments BuildChannelArguments(const OtlpGrpcClientOptions &options);
261+
257262
// Stores if this gRPC client had its Shutdown() method called
258263
std::atomic<bool> is_shutdown_;
259264

exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
namespace grpc
1414
{
1515
class ChannelCredentials;
16-
}
16+
class ChannelArguments;
17+
} // namespace grpc
1718

1819
OPENTELEMETRY_BEGIN_NAMESPACE
1920
namespace exporter
@@ -90,6 +91,13 @@ struct OtlpGrpcClientOptions
9091

9192
/** The backoff will be multiplied by this value after each retry attempt. */
9293
float retry_policy_backoff_multiplier{};
94+
95+
/**
96+
* Optional caller-provided gRPC channel arguments.
97+
* This is a non-owning pointer, and the pointed-to arguments are copied when the channel is
98+
* created.
99+
*/
100+
const grpc::ChannelArguments *channel_arguments{};
93101
};
94102

95103
} // namespace otlp

exporters/otlp/src/otlp_grpc_client.cc

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,52 @@ std::shared_ptr<grpc::Channel> OtlpGrpcClient::MakeChannel(const OtlpGrpcClientO
355355
return nullptr;
356356
}
357357

358+
grpc::ChannelArguments grpc_arguments = BuildChannelArguments(options);
359+
360+
if (options.use_ssl_credentials)
361+
{
362+
grpc::SslCredentialsOptions ssl_opts;
363+
ssl_opts.pem_root_certs = GetFileContentsOrInMemoryContents(
364+
options.ssl_credentials_cacert_path, options.ssl_credentials_cacert_as_string);
365+
#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW
366+
ssl_opts.pem_private_key = GetFileContentsOrInMemoryContents(options.ssl_client_key_path,
367+
options.ssl_client_key_string);
368+
ssl_opts.pem_cert_chain = GetFileContentsOrInMemoryContents(options.ssl_client_cert_path,
369+
options.ssl_client_cert_string);
370+
371+
#endif
372+
channel =
373+
grpc::CreateCustomChannel(grpc_target, grpc::SslCredentials(ssl_opts), grpc_arguments);
374+
}
375+
else
376+
{
377+
channel =
378+
grpc::CreateCustomChannel(grpc_target, grpc::InsecureChannelCredentials(), grpc_arguments);
379+
}
380+
381+
#ifdef ENABLE_OTLP_GRPC_CREDENTIAL_PREVIEW
382+
if (options.credentials)
383+
{
384+
if (options.use_ssl_credentials)
385+
{
386+
OTEL_INTERNAL_LOG_WARN(
387+
"[OTLP GRPC Client] Both 'credentials' and 'use_ssl_credentials' options are set. "
388+
"The former takes priority.");
389+
}
390+
channel = grpc::CreateCustomChannel(grpc_target, options.credentials, grpc_arguments);
391+
}
392+
#endif // ENABLE_OTLP_GRPC_CREDENTIAL_PREVIEW
393+
394+
return channel;
395+
}
396+
397+
grpc::ChannelArguments OtlpGrpcClient::BuildChannelArguments(const OtlpGrpcClientOptions &options)
398+
{
358399
grpc::ChannelArguments grpc_arguments;
400+
if (options.channel_arguments != nullptr)
401+
{
402+
grpc_arguments = *options.channel_arguments;
403+
}
359404
grpc_arguments.SetUserAgentPrefix(options.user_agent);
360405

361406
if (options.max_threads > 0)
@@ -399,9 +444,7 @@ std::shared_ptr<grpc::Channel> OtlpGrpcClient::MakeChannel(const OtlpGrpcClientO
399444
]
400445
})"};
401446

402-
// Allocate string with buffer large enough to hold the formatted json config
403447
auto service_config = std::string(kServiceConfigJson.size(), '\0');
404-
// Prior to C++17, need to explicitly cast away constness from `data()` buffer
405448
std::snprintf(
406449
const_cast<decltype(service_config)::value_type *>(service_config.data()),
407450
service_config.size(), kServiceConfigJson.data(), options.retry_policy_max_attempts,
@@ -413,41 +456,7 @@ std::shared_ptr<grpc::Channel> OtlpGrpcClient::MakeChannel(const OtlpGrpcClientO
413456
}
414457
#endif // ENABLE_OTLP_RETRY_PREVIEW
415458

416-
if (options.use_ssl_credentials)
417-
{
418-
grpc::SslCredentialsOptions ssl_opts;
419-
ssl_opts.pem_root_certs = GetFileContentsOrInMemoryContents(
420-
options.ssl_credentials_cacert_path, options.ssl_credentials_cacert_as_string);
421-
#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW
422-
ssl_opts.pem_private_key = GetFileContentsOrInMemoryContents(options.ssl_client_key_path,
423-
options.ssl_client_key_string);
424-
ssl_opts.pem_cert_chain = GetFileContentsOrInMemoryContents(options.ssl_client_cert_path,
425-
options.ssl_client_cert_string);
426-
427-
#endif
428-
channel =
429-
grpc::CreateCustomChannel(grpc_target, grpc::SslCredentials(ssl_opts), grpc_arguments);
430-
}
431-
else
432-
{
433-
channel =
434-
grpc::CreateCustomChannel(grpc_target, grpc::InsecureChannelCredentials(), grpc_arguments);
435-
}
436-
437-
#ifdef ENABLE_OTLP_GRPC_CREDENTIAL_PREVIEW
438-
if (options.credentials)
439-
{
440-
if (options.use_ssl_credentials)
441-
{
442-
OTEL_INTERNAL_LOG_WARN(
443-
"[OTLP GRPC Client] Both 'credentials' and 'use_ssl_credentials' options are set. "
444-
"The former takes priority.");
445-
}
446-
channel = grpc::CreateCustomChannel(grpc_target, options.credentials, grpc_arguments);
447-
}
448-
#endif // ENABLE_OTLP_GRPC_CREDENTIAL_PREVIEW
449-
450-
return channel;
459+
return grpc_arguments;
451460
}
452461

453462
std::unique_ptr<grpc::ClientContext> OtlpGrpcClient::MakeClientContext(

exporters/otlp/test/otlp_grpc_target_test.cc

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Copyright The OpenTelemetry Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4+
#include <grpcpp/support/channel_arguments.h>
45
#include <gtest/gtest.h>
5-
#include <string>
6+
7+
#include <cstring>
68

79
#include "opentelemetry/exporters/otlp/otlp_grpc_client.h"
810
#include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h"
@@ -14,6 +16,34 @@ namespace exporter
1416
namespace otlp
1517
{
1618

19+
namespace
20+
{
21+
22+
const grpc_arg *FindChannelArg(const grpc_channel_args &channel_args, const char *key)
23+
{
24+
for (std::size_t i = 0; i < channel_args.num_args; ++i)
25+
{
26+
const grpc_arg &arg = channel_args.args[i];
27+
if (arg.key != nullptr && std::strcmp(arg.key, key) == 0)
28+
{
29+
return &arg;
30+
}
31+
}
32+
33+
return nullptr;
34+
}
35+
36+
} // namespace
37+
38+
class OtlpGrpcClientTestPeer : public ::testing::Test
39+
{
40+
public:
41+
static grpc::ChannelArguments BuildChannelArguments(const OtlpGrpcClientOptions &options)
42+
{
43+
return OtlpGrpcClient::BuildChannelArguments(options);
44+
}
45+
};
46+
1747
TEST(OtlpGrpcClientEndpointTest, GrpcClientTest)
1848
{
1949
OtlpGrpcClientOptions opts1;
@@ -34,6 +64,35 @@ TEST(OtlpGrpcClientEndpointTest, GrpcClientTest)
3464
EXPECT_EQ(target3, "localhost:4317");
3565
}
3666

67+
TEST_F(OtlpGrpcClientTestPeer, ChannelArgumentsOptionTest)
68+
{
69+
OtlpGrpcClientOptions options;
70+
options.user_agent = "otlp-grpc-target-test";
71+
72+
grpc::ChannelArguments channel_arguments;
73+
channel_arguments.SetMaxReceiveMessageSize(1);
74+
options.channel_arguments = &channel_arguments;
75+
76+
auto built_arguments = BuildChannelArguments(options);
77+
channel_arguments.SetMaxReceiveMessageSize(-1);
78+
79+
auto built_channel_args = built_arguments.c_channel_args();
80+
81+
const grpc_arg *max_receive_arg =
82+
FindChannelArg(built_channel_args, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH);
83+
ASSERT_NE(max_receive_arg, nullptr);
84+
EXPECT_EQ(max_receive_arg->type, GRPC_ARG_INTEGER);
85+
EXPECT_EQ(max_receive_arg->value.integer, 1);
86+
87+
const grpc_arg *user_agent_arg =
88+
FindChannelArg(built_channel_args, GRPC_ARG_PRIMARY_USER_AGENT_STRING);
89+
ASSERT_NE(user_agent_arg, nullptr);
90+
EXPECT_EQ(user_agent_arg->type, GRPC_ARG_STRING);
91+
EXPECT_EQ(std::strncmp(user_agent_arg->value.string, options.user_agent.c_str(),
92+
options.user_agent.size()),
93+
0);
94+
}
95+
3796
} // namespace otlp
3897
} // namespace exporter
3998
OPENTELEMETRY_END_NAMESPACE

0 commit comments

Comments
 (0)