diff --git a/google/cloud/storage/grpc_plugin.h b/google/cloud/storage/grpc_plugin.h index 045c0f7fea0c5..167ecb8dcb609 100644 --- a/google/cloud/storage/grpc_plugin.h +++ b/google/cloud/storage/grpc_plugin.h @@ -102,6 +102,35 @@ struct GrpcMetricsPeriodOption { using Type = std::chrono::seconds; }; +/** + * gRPC telemetry export timeout. + * + * When `EnableGrpcMetrics` is enabled, this option controls the maximum time + * to wait for metrics to be exported to [Google Cloud Monitoring]. The default + * is 30 seconds. + * + * This timeout is particularly important for short-lived programs. Setting a + * lower timeout ensures metrics are flushed before the program exits. For + * long-running services, the default value is appropriate. + * + * @par Example: Configure for short-lived programs + * @code + * namespace gcs_ex = google::cloud::storage_experimental; + * auto client = google::cloud::storage::MakeGrpcClient( + * google::cloud::Options{} + * .set(true) + * .set( + * std::chrono::seconds(5)) + * .set( + * std::chrono::seconds(2))); + * @endcode + * + * [Google Cloud Monitoring]: https://cloud.google.com/monitoring/docs + */ +struct GrpcMetricsExportTimeoutOption { + using Type = std::chrono::seconds; +}; + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_experimental } // namespace cloud diff --git a/google/cloud/storage/internal/grpc/default_options.cc b/google/cloud/storage/internal/grpc/default_options.cc index e693ace81ad81..abd150c40d9ea 100644 --- a/google/cloud/storage/internal/grpc/default_options.cc +++ b/google/cloud/storage/internal/grpc/default_options.cc @@ -36,6 +36,7 @@ namespace { auto constexpr kMinMetricsPeriod = std::chrono::seconds(5); auto constexpr kDefaultMetricsPeriod = std::chrono::seconds(60); +auto constexpr kDefaultMetricsExportTimeout = std::chrono::seconds(30); int DefaultGrpcNumChannels(std::string const& endpoint) { // When using Direct Connectivity the gRPC library already does load balancing @@ -112,7 +113,9 @@ Options DefaultOptionsGrpc( .set( enable_grpc_metrics) .set( - kDefaultMetricsPeriod)); + kDefaultMetricsPeriod) + .set( + kDefaultMetricsExportTimeout)); if (options.get() < kMinMetricsPeriod) { options.set( diff --git a/google/cloud/storage/internal/grpc/metrics_exporter_impl.cc b/google/cloud/storage/internal/grpc/metrics_exporter_impl.cc index 9e883d20852bd..2e6ae92ba5a6f 100644 --- a/google/cloud/storage/internal/grpc/metrics_exporter_impl.cc +++ b/google/cloud/storage/internal/grpc/metrics_exporter_impl.cc @@ -49,8 +49,8 @@ auto MakeReaderOptions(Options const& options) { opentelemetry::sdk::metrics::PeriodicExportingMetricReaderOptions{}; reader_options.export_interval_millis = std::chrono::milliseconds( options.get()); - reader_options.export_timeout_millis = - std::chrono::milliseconds(std::chrono::seconds(30)); + reader_options.export_timeout_millis = std::chrono::milliseconds( + options.get()); return reader_options; } diff --git a/google/cloud/storage/internal/grpc/metrics_exporter_impl_test.cc b/google/cloud/storage/internal/grpc/metrics_exporter_impl_test.cc index 59348cc42763a..b266f262c61e9 100644 --- a/google/cloud/storage/internal/grpc/metrics_exporter_impl_test.cc +++ b/google/cloud/storage/internal/grpc/metrics_exporter_impl_test.cc @@ -110,6 +110,52 @@ TEST(GrpcMetricsExporter, EnabledWithTimeout) { std::chrono::milliseconds(0)); } +TEST(GrpcMetricsExporter, DefaultExportTime) { + auto config = MakeMeterProviderConfig(FullResource(), TestOptions()); + ASSERT_TRUE(config.has_value()); + EXPECT_EQ(config->project, Project("project-id-resource")); + EXPECT_EQ(config->reader_options.export_interval_millis, + std::chrono::seconds(60)); + EXPECT_EQ(config->reader_options.export_timeout_millis, + std::chrono::seconds(30)); +} + +TEST(GrpcMetricsExporter, CustomExportTime) { + auto config = MakeMeterProviderConfig( + FullResource(), + TestOptions() + .set( + std::chrono::seconds(10)) + .set( + std::chrono::seconds(2))); + ASSERT_TRUE(config.has_value()); + EXPECT_EQ(config->project, Project("project-id-resource")); + EXPECT_EQ(config->reader_options.export_interval_millis, + std::chrono::seconds(10)); + EXPECT_EQ(config->reader_options.export_timeout_millis, + std::chrono::seconds(2)); +} + +TEST(GrpcMetricsExporter, ReaderOptionsAreSetFromConfig) { + auto const expected_interval = std::chrono::seconds(45); + auto const expected_timeout = std::chrono::seconds(25); + + auto config = MakeMeterProviderConfig( + FullResource(), + TestOptions() + .set(expected_interval) + .set( + expected_timeout)); + + ASSERT_TRUE(config.has_value()); + + // Verify the conversion from seconds to milliseconds happens correctly. + EXPECT_EQ(config->reader_options.export_interval_millis, + std::chrono::milliseconds(expected_interval)); + EXPECT_EQ(config->reader_options.export_timeout_millis, + std::chrono::milliseconds(expected_timeout)); +} + } // namespace GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_internal