Skip to content

Commit f183833

Browse files
authored
Merge pull request #153 from open-telemetry/main
[EXPORTER] Support handling retry-able errors for OTLP/gRPC (open-telemetry#3219)
2 parents 4a43da6 + 031307b commit f183833

12 files changed

+388
-21
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ Increment the:
3636
* [EXPORTER] Support handling retry-able errors for OTLP/HTTP
3737
[#3223](https://github.com/open-telemetry/opentelemetry-cpp/pull/3223)
3838

39+
* [EXPORTER] Support handling retry-able errors for OTLP/gRPC
40+
[#3219](https://github.com/open-telemetry/opentelemetry-cpp/pull/3219)
41+
3942
New features:
4043

4144
* [SDK] Better control of threads executed by opentelemetry-cpp

ci/do_ci.sh

+1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ elif [[ "$1" == "cmake.exporter.otprotocol.test" ]]; then
347347
-DWITH_OTLP_HTTP=ON \
348348
-DWITH_OTLP_FILE=ON \
349349
-DWITH_OTLP_GRPC_SSL_MTLS_PREVIEW=ON \
350+
-DWITH_OTLP_RETRY_PREVIEW=ON \
350351
"${SRC_DIR}"
351352
grpc_cpp_plugin=`which grpc_cpp_plugin`
352353
proto_make_file="CMakeFiles/opentelemetry_proto.dir/build.make"

exporters/otlp/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ if(BUILD_TESTING)
317317
add_executable(otlp_grpc_exporter_test test/otlp_grpc_exporter_test.cc)
318318
target_link_libraries(
319319
otlp_grpc_exporter_test ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
320-
${GMOCK_LIB} opentelemetry_exporter_otlp_grpc)
320+
${GMOCK_LIB} opentelemetry_exporter_otlp_grpc gRPC::grpc++)
321321
gtest_add_tests(
322322
TARGET otlp_grpc_exporter_test
323323
TEST_PREFIX exporter.otlp.

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

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ struct OtlpGrpcClientOptions
6262
// Concurrent requests
6363
std::size_t max_concurrent_requests;
6464
#endif
65+
66+
/** The maximum number of call attempts, including the original attempt. */
67+
std::uint32_t retry_policy_max_attempts{};
68+
69+
/** The initial backoff delay between retry attempts, random between (0, initial_backoff). */
70+
std::chrono::duration<float> retry_policy_initial_backoff{};
71+
72+
/** The maximum backoff places an upper limit on exponential backoff growth. */
73+
std::chrono::duration<float> retry_policy_max_backoff{};
74+
75+
/** The backoff will be multiplied by this value after each retry attempt. */
76+
float retry_policy_backoff_multiplier{};
6577
};
6678

6779
} // namespace otlp

exporters/otlp/src/otlp_grpc_client.cc

+45
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <atomic>
1313
#include <chrono>
1414
#include <condition_variable>
15+
#include <cstdio>
1516
#include <fstream>
1617
#include <iterator>
1718
#include <memory>
@@ -23,6 +24,7 @@
2324
#include "opentelemetry/common/timestamp.h"
2425
#include "opentelemetry/ext/http/common/url_parser.h"
2526
#include "opentelemetry/nostd/function_ref.h"
27+
#include "opentelemetry/nostd/string_view.h"
2628
#include "opentelemetry/sdk/common/global_log_handler.h"
2729

2830
OPENTELEMETRY_BEGIN_NAMESPACE
@@ -347,6 +349,49 @@ std::shared_ptr<grpc::Channel> OtlpGrpcClient::MakeChannel(const OtlpGrpcClientO
347349
grpc_arguments.SetCompressionAlgorithm(GRPC_COMPRESS_GZIP);
348350
}
349351

352+
#ifdef ENABLE_OTLP_RETRY_PREVIEW
353+
if (options.retry_policy_max_attempts > 0U &&
354+
options.retry_policy_initial_backoff > std::chrono::duration<float>::zero() &&
355+
options.retry_policy_max_backoff > std::chrono::duration<float>::zero() &&
356+
options.retry_policy_backoff_multiplier > 0.0f)
357+
{
358+
static const auto kServiceConfigJson = opentelemetry::nostd::string_view{R"(
359+
{
360+
"methodConfig": [
361+
{
362+
"name": [{}],
363+
"retryPolicy": {
364+
"maxAttempts": %0000000000u,
365+
"initialBackoff": "%0000000000.1fs",
366+
"maxBackoff": "%0000000000.1fs",
367+
"backoffMultiplier": %0000000000.1f,
368+
"retryableStatusCodes": [
369+
"CANCELLED",
370+
"DEADLINE_EXCEEDED",
371+
"ABORTED",
372+
"OUT_OF_RANGE",
373+
"DATA_LOSS",
374+
"UNAVAILABLE"
375+
]
376+
}
377+
}
378+
]
379+
})"};
380+
381+
// Allocate string with buffer large enough to hold the formatted json config
382+
auto service_config = std::string(kServiceConfigJson.size(), '\0');
383+
// Prior to C++17, need to explicitly cast away constness from `data()` buffer
384+
std::snprintf(
385+
const_cast<decltype(service_config)::value_type *>(service_config.data()),
386+
service_config.size(), kServiceConfigJson.data(), options.retry_policy_max_attempts,
387+
std::min(std::max(options.retry_policy_initial_backoff.count(), 0.f), 999999999.f),
388+
std::min(std::max(options.retry_policy_max_backoff.count(), 0.f), 999999999.f),
389+
std::min(std::max(options.retry_policy_backoff_multiplier, 0.f), 999999999.f));
390+
391+
grpc_arguments.SetServiceConfigJSON(service_config);
392+
}
393+
#endif // ENABLE_OTLP_RETRY_PREVIEW
394+
350395
if (options.use_ssl_credentials)
351396
{
352397
grpc::SslCredentialsOptions ssl_opts;

exporters/otlp/src/otlp_grpc_exporter.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ sdk::common::ExportResult OtlpGrpcExporter::Export(
105105
google::protobuf::ArenaOptions arena_options;
106106
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
107107
arena_options.initial_block_size = 1024;
108-
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
108+
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a larger
109109
// block to reduce memory fragments.
110110
arena_options.max_block_size = 65536;
111111
std::unique_ptr<google::protobuf::Arena> arena{new google::protobuf::Arena{arena_options}};

exporters/otlp/src/otlp_grpc_exporter_options.cc

+5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ OtlpGrpcExporterOptions::OtlpGrpcExporterOptions()
3636
#ifdef ENABLE_ASYNC_EXPORT
3737
max_concurrent_requests = 64;
3838
#endif
39+
40+
retry_policy_max_attempts = GetOtlpDefaultTracesRetryMaxAttempts();
41+
retry_policy_initial_backoff = GetOtlpDefaultTracesRetryInitialBackoff();
42+
retry_policy_max_backoff = GetOtlpDefaultTracesRetryMaxBackoff();
43+
retry_policy_backoff_multiplier = GetOtlpDefaultTracesRetryBackoffMultiplier();
3944
}
4045

4146
OtlpGrpcExporterOptions::~OtlpGrpcExporterOptions() {}

exporters/otlp/src/otlp_grpc_log_record_exporter_options.cc

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ OtlpGrpcLogRecordExporterOptions::OtlpGrpcLogRecordExporterOptions()
3434
#ifdef ENABLE_ASYNC_EXPORT
3535
max_concurrent_requests = 64;
3636
#endif
37+
38+
retry_policy_max_attempts = GetOtlpDefaultLogsRetryMaxAttempts();
39+
retry_policy_initial_backoff = GetOtlpDefaultLogsRetryInitialBackoff();
40+
retry_policy_max_backoff = GetOtlpDefaultLogsRetryMaxBackoff();
41+
retry_policy_backoff_multiplier = GetOtlpDefaultLogsRetryBackoffMultiplier();
3742
}
3843

3944
OtlpGrpcLogRecordExporterOptions::~OtlpGrpcLogRecordExporterOptions() {}

exporters/otlp/src/otlp_grpc_metric_exporter_options.cc

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ OtlpGrpcMetricExporterOptions::OtlpGrpcMetricExporterOptions()
3535
#ifdef ENABLE_ASYNC_EXPORT
3636
max_concurrent_requests = 64;
3737
#endif
38+
39+
retry_policy_max_attempts = GetOtlpDefaultMetricsRetryMaxAttempts();
40+
retry_policy_initial_backoff = GetOtlpDefaultMetricsRetryInitialBackoff();
41+
retry_policy_max_backoff = GetOtlpDefaultMetricsRetryMaxBackoff();
42+
retry_policy_backoff_multiplier = GetOtlpDefaultMetricsRetryBackoffMultiplier();
3843
}
3944

4045
OtlpGrpcMetricExporterOptions::~OtlpGrpcMetricExporterOptions() {}

0 commit comments

Comments
 (0)