Update OtlpGrpcClientOptions to populate options for gRPC client sharing#4249
Update OtlpGrpcClientOptions to populate options for gRPC client sharing#4249ML-dev-crypto wants to merge 3 commits into
Conversation
Fixes open-telemetry#4239 OtlpGrpcClientOptions previously only had a = default constructor, leaving every option at null/zero. Add a real default constructor that populates spec-compliant defaults from generic (signal-independent) OTEL_EXPORTER_OTLP_* environment variables, a void* constructor that skips defaults, and a constructor on each of OtlpGrpcExporterOptions, OtlpGrpcMetricExporterOptions, and OtlpGrpcLogRecordExporterOptions that builds from a shared OtlpGrpcClientOptions, copying client-fixed fields and overriding only timeout, metadata, and max_concurrent_requests per signal. Signed-off-by: Ansh Rai <anshrai331@gmail.com>
|
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4249 +/- ##
==========================================
+ Coverage 77.92% 78.15% +0.24%
==========================================
Files 439 440 +1
Lines 18612 18754 +142
==========================================
+ Hits 14502 14656 +154
+ Misses 4110 4098 -12
🚀 New features to boost your workflow:
|
Signed-off-by: Ansh Rai <anshrai331@gmail.com>
| { | ||
| virtual ~OtlpGrpcClientOptions() = default; | ||
| OtlpGrpcClientOptions() = default; | ||
| virtual ~OtlpGrpcClientOptions(); |
There was a problem hiding this comment.
In my understanding, if we implement public struct or function in .cc files. We need to use OPENTELEMETRY_EXPORT to export them. Or the symbols will be hidden and cause link error in some situation.
There was a problem hiding this comment.
You're right, I missed that. I'll add OPENTELEMETRY_EXPORT.
| namespace otlp | ||
| { | ||
|
|
||
| OtlpGrpcClientOptions::OtlpGrpcClientOptions() |
There was a problem hiding this comment.
Should members be initialized in a member initializer of the constructor to avoid cppcoreguidelines-prefer-member-initializer of clang-tidy?
There was a problem hiding this comment.
Good point. I'll switch these to use a member initializer list to satisfy cppcoreguidelines-prefer-member-initializer.
| inline std::string GetOtlpDefaultGrpcClientSslClientKeyPath() | ||
| { | ||
| std::string value; | ||
| opentelemetry::sdk::common::GetStringEnvironmentVariable("OTEL_EXPORTER_OTLP_CLIENT_KEY", value); |
There was a problem hiding this comment.
I'd suggest moving these environment variable definitions to a shared location so both this file and otlp_environment.cc can reference the same constants. This will make maintenance easier going forward.
There was a problem hiding this comment.
Agreed. The generic OTLP environment variable names are duplicated now, so I'll move them to a shared location that both the header and implementation can reference.
|
|
||
| std::unordered_set<std::string> remove_cache; | ||
|
|
||
| while (tokenizer.next(header_valid, header_key, header_value)) |
There was a problem hiding this comment.
Why not export and use DumpOtlpHeaders here?
There was a problem hiding this comment.
Makes sense. I duplicated the parsing logic because DumpOtlpHeaders isn't currently reusable, but I agree it's better to avoid the duplication. I'll refactor this to reuse the existing implementation.
| * environment variables and fall back to the same spec defaults used above. | ||
| */ | ||
|
|
||
| inline std::string GetOtlpDefaultGrpcClientEndpoint() |
There was a problem hiding this comment.
We should move these implementations into otlp_environment.cc to reduce symbol size.
Also, the inline keyword is merely a hint to the compiler, not a mandatory directive. Different compilers may make different inlining decisions under different optimization flags, which can lead to inconsistent symbol generation.
For example, in Release builds the compiler might fully inline these functions and omit external symbols. Later, when a Debug build links against this library, the linker may not resolve those symbols, resulting in undefined references at link time.
There was a problem hiding this comment.
Good point. I'll move these helper implementations out of the header and keep them alongside the existing environment accessors while making sure the dependency structure still works.
There was a problem hiding this comment.
Should we use OtlpGrpcClientOptions(nullptr) here and in constructor of metrics and logs options to avoid unnecessary environment parsing?
There was a problem hiding this comment.
Agreed.I'll update this to reuse the base constructor and only override the signal-specific fields.
| metadata = GetOtlpDefaultTracesHeaders(); | ||
|
|
||
| #ifdef ENABLE_ASYNC_EXPORT | ||
| max_concurrent_requests = 64; |
There was a problem hiding this comment.
Why reset max_concurrent_requests here?
There was a problem hiding this comment.
Thanks for catching that,The intention was to preserve the shared client's configured value, so I'll update this constructor to copy max_concurrent_requests instead of resetting it.
| metadata = GetOtlpDefaultLogsHeaders(); | ||
|
|
||
| #ifdef ENABLE_ASYNC_EXPORT | ||
| max_concurrent_requests = 64; |
There was a problem hiding this comment.
Just as above, why reset max_concurrent_requests here?
There was a problem hiding this comment.
Thanks! I'll make the same change here as well.
|
Thanks for the thorough review, @owent! I'll address all of these comments in a follow-up commit, including the export annotation, constructor initialization cleanup, shared environment variable definitions, removal of the duplicated header parsing logic, moving the new environment helpers out of the header, reusing the base constructor for shared client initialization, and preserving the shared client's |
Signed-off-by: Ansh Rai <anshrai331@gmail.com>
Fixes #4239
OtlpGrpcClientOptionspreviously only had a= defaultconstructor,leaving every option at null/zero regardless of environment variables
or otel-spec defaults. This made it impossible to build a standalone
OtlpGrpcClientwith spec-compliant defaults for sharing across thetrace/metric/log exporters, as described in the issue.
Changes:
accessors to
otlp_environment.h, e.g.GetOtlpDefaultGrpcClientEndpoint().These are
inline, defined in the header rather thanotlp_environment.cc, so thatotlp_grpc_client(a lean transport-onlytarget) doesn't need to depend on
otlp_recordableand itssdk/logs, sdk/metrics, sdk/trace dependencies just to read an env var.
OtlpGrpcClientOptionsnow has a real default constructor (in a newotlp_grpc_client_options.cc) that populates from those accessors,and a
void*constructor that skips populating, for parity with theexisting per-signal options classes.
OtlpGrpcExporterOptions/OtlpGrpcMetricExporterOptions/OtlpGrpcLogRecordExporterOptionseach gained a constructor taking aconst OtlpGrpcClientOptions&, copying the client-fixed fields(endpoint, SSL/mTLS fields, credentials, user_agent, channel_arguments,
max_threads, compression, retry policy) and overriding only the fields
that may still differ per signal (timeout, metadata,
max_concurrent_requests) — per the table in the issue.
(
//sdk/src/common:env_variables); no new library targets, no changeto the existing dependency graph shape.
otlp_grpc_client_options_test.cccovering: defaultenv-var population, the
void*no-defaults path (including thederived classes'
void*constructors), fixed-field copying from ashared client, and signal-specific env-var precedence over the
shared client's generic value.
Tested: compiled and unit-tested with both GCC/libstdc++ and
MSVC/STL;
clang-formatapplied.