diff --git a/generator/generator_config.textproto b/generator/generator_config.textproto index 1c883c1523100..4457ff4e00082 100644 --- a/generator/generator_config.textproto +++ b/generator/generator_config.textproto @@ -941,6 +941,7 @@ service { service_proto_path: "google/logging/v2/logging.proto" product_path: "google/cloud/logging" initial_copyright_year: "2021" + gen_async_rpcs: ["WriteLogEntries"] retryable_status_codes: ["kInternal", "kUnavailable"] } diff --git a/google/cloud/logging/internal/logging_service_v2_auth_decorator.cc b/google/cloud/logging/internal/logging_service_v2_auth_decorator.cc index 9a9fc1392c782..fef57875d670e 100644 --- a/google/cloud/logging/internal/logging_service_v2_auth_decorator.cc +++ b/google/cloud/logging/internal/logging_service_v2_auth_decorator.cc @@ -93,6 +93,25 @@ LoggingServiceV2Auth::AsyncTailLogEntries( std::move(context), auth_, StreamAuth::StreamFactory(std::move(call))); } +future> +LoggingServiceV2Auth::AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) { + using ReturnType = StatusOr; + auto& child = child_; + return auth_->AsyncConfigureContext(std::move(context)) + .then([cq, child, + request](future>> + f) mutable { + auto context = f.get(); + if (!context) { + return make_ready_future(ReturnType(std::move(context).status())); + } + return child->AsyncWriteLogEntries(cq, *std::move(context), request); + }); +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace logging_internal } // namespace cloud diff --git a/google/cloud/logging/internal/logging_service_v2_auth_decorator.h b/google/cloud/logging/internal/logging_service_v2_auth_decorator.h index 0e2981f2824fc..f5769986fe59a 100644 --- a/google/cloud/logging/internal/logging_service_v2_auth_decorator.h +++ b/google/cloud/logging/internal/logging_service_v2_auth_decorator.h @@ -66,6 +66,12 @@ class LoggingServiceV2Auth : public LoggingServiceV2Stub { AsyncTailLogEntries(google::cloud::CompletionQueue const& cq, std::unique_ptr context) override; + future> + AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) override; + private: std::shared_ptr auth_; std::shared_ptr child_; diff --git a/google/cloud/logging/internal/logging_service_v2_connection_impl.cc b/google/cloud/logging/internal/logging_service_v2_connection_impl.cc index 0a006250c27c6..4c4f29d008450 100644 --- a/google/cloud/logging/internal/logging_service_v2_connection_impl.cc +++ b/google/cloud/logging/internal/logging_service_v2_connection_impl.cc @@ -21,6 +21,7 @@ #include "google/cloud/background_threads.h" #include "google/cloud/common_options.h" #include "google/cloud/grpc_options.h" +#include "google/cloud/internal/async_retry_loop.h" #include "google/cloud/internal/pagination_range.h" #include "google/cloud/internal/retry_loop.h" #include @@ -159,6 +160,20 @@ StreamRange LoggingServiceV2ConnectionImpl::ListLogs( }); } +future> +LoggingServiceV2ConnectionImpl::AsyncWriteLogEntries( + google::logging::v2::WriteLogEntriesRequest const& request) { + auto& stub = stub_; + return google::cloud::internal::AsyncRetryLoop( + retry_policy(), backoff_policy(), + idempotency_policy()->WriteLogEntries(request), background_->cq(), + [stub](CompletionQueue& cq, std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) { + return stub->AsyncWriteLogEntries(cq, std::move(context), request); + }, + request, __func__); +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace logging_internal } // namespace cloud diff --git a/google/cloud/logging/internal/logging_service_v2_connection_impl.h b/google/cloud/logging/internal/logging_service_v2_connection_impl.h index 1f3dffac1ab18..6d2380cc00df6 100644 --- a/google/cloud/logging/internal/logging_service_v2_connection_impl.h +++ b/google/cloud/logging/internal/logging_service_v2_connection_impl.h @@ -72,6 +72,10 @@ class LoggingServiceV2ConnectionImpl google::logging::v2::TailLogEntriesResponse>> AsyncTailLogEntries(ExperimentalTag) override; + future> + AsyncWriteLogEntries( + google::logging::v2::WriteLogEntriesRequest const& request) override; + private: std::unique_ptr retry_policy() { auto const& options = internal::CurrentOptions(); diff --git a/google/cloud/logging/internal/logging_service_v2_logging_decorator.cc b/google/cloud/logging/internal/logging_service_v2_logging_decorator.cc index aaf4c9c768609..b62d43928efaa 100644 --- a/google/cloud/logging/internal/logging_service_v2_logging_decorator.cc +++ b/google/cloud/logging/internal/logging_service_v2_logging_decorator.cc @@ -117,6 +117,20 @@ LoggingServiceV2Logging::AsyncTailLogEntries( return stream; } +future> +LoggingServiceV2Logging::AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) { + return google::cloud::internal::LogWrapper( + [this](google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) { + return child_->AsyncWriteLogEntries(cq, std::move(context), request); + }, + cq, std::move(context), request, __func__, tracing_options_); +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace logging_internal } // namespace cloud diff --git a/google/cloud/logging/internal/logging_service_v2_logging_decorator.h b/google/cloud/logging/internal/logging_service_v2_logging_decorator.h index f18cf91c803f5..860f3daa02b4b 100644 --- a/google/cloud/logging/internal/logging_service_v2_logging_decorator.h +++ b/google/cloud/logging/internal/logging_service_v2_logging_decorator.h @@ -66,6 +66,12 @@ class LoggingServiceV2Logging : public LoggingServiceV2Stub { AsyncTailLogEntries(google::cloud::CompletionQueue const& cq, std::unique_ptr context) override; + future> + AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) override; + private: std::shared_ptr child_; TracingOptions tracing_options_; diff --git a/google/cloud/logging/internal/logging_service_v2_metadata_decorator.cc b/google/cloud/logging/internal/logging_service_v2_metadata_decorator.cc index 95be662f75bb4..b3b13480e90ea 100644 --- a/google/cloud/logging/internal/logging_service_v2_metadata_decorator.cc +++ b/google/cloud/logging/internal/logging_service_v2_metadata_decorator.cc @@ -84,6 +84,15 @@ LoggingServiceV2Metadata::AsyncTailLogEntries( return child_->AsyncTailLogEntries(cq, std::move(context)); } +future> +LoggingServiceV2Metadata::AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) { + SetMetadata(*context); + return child_->AsyncWriteLogEntries(cq, std::move(context), request); +} + void LoggingServiceV2Metadata::SetMetadata(grpc::ClientContext& context, std::string const& request_params) { context.AddMetadata("x-goog-request-params", request_params); diff --git a/google/cloud/logging/internal/logging_service_v2_metadata_decorator.h b/google/cloud/logging/internal/logging_service_v2_metadata_decorator.h index 086075595b7cc..c4b38f4d48418 100644 --- a/google/cloud/logging/internal/logging_service_v2_metadata_decorator.h +++ b/google/cloud/logging/internal/logging_service_v2_metadata_decorator.h @@ -63,6 +63,12 @@ class LoggingServiceV2Metadata : public LoggingServiceV2Stub { AsyncTailLogEntries(google::cloud::CompletionQueue const& cq, std::unique_ptr context) override; + future> + AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) override; + private: void SetMetadata(grpc::ClientContext& context, std::string const& request_params); diff --git a/google/cloud/logging/internal/logging_service_v2_stub.cc b/google/cloud/logging/internal/logging_service_v2_stub.cc index 6b75f0735be03..64f059552aca3 100644 --- a/google/cloud/logging/internal/logging_service_v2_stub.cc +++ b/google/cloud/logging/internal/logging_service_v2_stub.cc @@ -107,6 +107,20 @@ DefaultLoggingServiceV2Stub::AsyncTailLogEntries( }); } +future> +DefaultLoggingServiceV2Stub::AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) { + return cq.MakeUnaryRpc( + [this](grpc::ClientContext* context, + google::logging::v2::WriteLogEntriesRequest const& request, + grpc::CompletionQueue* cq) { + return grpc_stub_->AsyncWriteLogEntries(context, request, cq); + }, + request, std::move(context)); +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace logging_internal } // namespace cloud diff --git a/google/cloud/logging/internal/logging_service_v2_stub.h b/google/cloud/logging/internal/logging_service_v2_stub.h index c10c83c2c1a00..4208acfe253d2 100644 --- a/google/cloud/logging/internal/logging_service_v2_stub.h +++ b/google/cloud/logging/internal/logging_service_v2_stub.h @@ -21,6 +21,7 @@ #include "google/cloud/async_streaming_read_write_rpc.h" #include "google/cloud/completion_queue.h" +#include "google/cloud/future.h" #include "google/cloud/status_or.h" #include "google/cloud/version.h" #include @@ -64,6 +65,12 @@ class LoggingServiceV2Stub { google::logging::v2::TailLogEntriesResponse>> AsyncTailLogEntries(google::cloud::CompletionQueue const& cq, std::unique_ptr context) = 0; + + virtual future> + AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) = 0; }; class DefaultLoggingServiceV2Stub : public LoggingServiceV2Stub { @@ -101,6 +108,12 @@ class DefaultLoggingServiceV2Stub : public LoggingServiceV2Stub { AsyncTailLogEntries(google::cloud::CompletionQueue const& cq, std::unique_ptr context) override; + future> + AsyncWriteLogEntries( + google::cloud::CompletionQueue& cq, + std::unique_ptr context, + google::logging::v2::WriteLogEntriesRequest const& request) override; + private: std::unique_ptr grpc_stub_; diff --git a/google/cloud/logging/logging_service_v2_client.cc b/google/cloud/logging/logging_service_v2_client.cc index 2cb9842c6a13d..6cee17bee11cb 100644 --- a/google/cloud/logging/logging_service_v2_client.cc +++ b/google/cloud/logging/logging_service_v2_client.cc @@ -116,6 +116,27 @@ LoggingServiceV2Client::AsyncTailLogEntries(ExperimentalTag tag, Options opts) { return connection_->AsyncTailLogEntries(std::move(tag)); } +future> +LoggingServiceV2Client::AsyncWriteLogEntries( + std::string const& log_name, google::api::MonitoredResource const& resource, + std::map const& labels, + std::vector const& entries, Options opts) { + internal::OptionsSpan span(internal::MergeOptions(std::move(opts), options_)); + google::logging::v2::WriteLogEntriesRequest request; + request.set_log_name(log_name); + *request.mutable_resource() = resource; + *request.mutable_labels() = {labels.begin(), labels.end()}; + *request.mutable_entries() = {entries.begin(), entries.end()}; + return connection_->AsyncWriteLogEntries(request); +} + +future> +LoggingServiceV2Client::AsyncWriteLogEntries( + google::logging::v2::WriteLogEntriesRequest const& request, Options opts) { + internal::OptionsSpan span(internal::MergeOptions(std::move(opts), options_)); + return connection_->AsyncWriteLogEntries(request); +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace logging } // namespace cloud diff --git a/google/cloud/logging/logging_service_v2_client.h b/google/cloud/logging/logging_service_v2_client.h index b9d57fc721805..385f0356c9f7e 100644 --- a/google/cloud/logging/logging_service_v2_client.h +++ b/google/cloud/logging/logging_service_v2_client.h @@ -376,6 +376,107 @@ class LoggingServiceV2Client { google::logging::v2::TailLogEntriesResponse>> AsyncTailLogEntries(ExperimentalTag, Options opts = {}); + /// + /// Writes log entries to Logging. This API method is the + /// only way to send log entries to Logging. This method + /// is used, directly or indirectly, by the Logging agent + /// (fluentd) and all logging libraries configured to use Logging. + /// A single request may contain log entries for a maximum of 1000 + /// different resources (projects, organizations, billing accounts or + /// folders) + /// + /// @param log_name Optional. A default log resource name that is assigned to + /// all log entries + /// in `entries` that do not specify a value for `log_name`: + /// * `projects/[PROJECT_ID]/logs/[LOG_ID]` + /// * `organizations/[ORGANIZATION_ID]/logs/[LOG_ID]` + /// * `billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]` + /// * `folders/[FOLDER_ID]/logs/[LOG_ID]` + /// `[LOG_ID]` must be URL-encoded. For example: + /// "projects/my-project-id/logs/syslog" + /// "organizations/123/logs/cloudaudit.googleapis.com%2Factivity" + /// The permission `logging.logEntries.create` is needed on each project, + /// organization, billing account, or folder that is receiving new log + /// entries, whether the resource is specified in `logName` or in an + /// individual log entry. + /// @param resource Optional. A default monitored resource object that is + /// assigned to all log + /// entries in `entries` that do not specify a value for `resource`. Example: + /// { "type": "gce_instance", + /// "labels": { + /// "zone": "us-central1-a", "instance_id": "00000000000000000000" }} + /// See [LogEntry][google.logging.v2.LogEntry]. + /// @param labels Optional. Default labels that are added to the `labels` + /// field of all log + /// entries in `entries`. If a log entry already has a label with the same + /// key as a label in this parameter, then the log entry's label is not + /// changed. See [LogEntry][google.logging.v2.LogEntry]. + /// @param entries Required. The log entries to send to Logging. The order of + /// log + /// entries in this list does not matter. Values supplied in this method's + /// `log_name`, `resource`, and `labels` fields are copied into those log + /// entries in this list that do not include values for their corresponding + /// fields. For more information, see the + /// [LogEntry][google.logging.v2.LogEntry] type. + /// If the `timestamp` or `insert_id` fields are missing in log entries, then + /// this method supplies the current time or a unique identifier, + /// respectively. The supplied values are chosen so that, among the log + /// entries that did not supply their own values, the entries earlier in the + /// list will sort before the entries later in the list. See the + /// `entries.list` method. Log entries with timestamps that are more than the + /// [logs retention period](https://cloud.google.com/logging/quotas) in + /// the past or more than 24 hours in the future will not be available when + /// calling `entries.list`. However, those log entries can still be [exported + /// with + /// LogSinks](https://cloud.google.com/logging/docs/api/tasks/exporting-logs). + /// To improve throughput and to avoid exceeding the + /// [quota limit](https://cloud.google.com/logging/quotas) for calls to + /// `entries.write`, you should try to include several log entries in this + /// list, rather than calling this method for each individual log entry. + /// @param opts Optional. Override the class-level options, such as retry and + /// backoff policies. + /// @return + /// @googleapis_link{google::logging::v2::WriteLogEntriesResponse,google/logging/v2/logging.proto#L241} + /// + /// [google.logging.v2.WriteLogEntriesRequest]: + /// @googleapis_reference_link{google/logging/v2/logging.proto#L160} + /// [google.logging.v2.WriteLogEntriesResponse]: + /// @googleapis_reference_link{google/logging/v2/logging.proto#L241} + /// + future> + AsyncWriteLogEntries( + std::string const& log_name, + google::api::MonitoredResource const& resource, + std::map const& labels, + std::vector const& entries, + Options opts = {}); + + /// + /// Writes log entries to Logging. This API method is the + /// only way to send log entries to Logging. This method + /// is used, directly or indirectly, by the Logging agent + /// (fluentd) and all logging libraries configured to use Logging. + /// A single request may contain log entries for a maximum of 1000 + /// different resources (projects, organizations, billing accounts or + /// folders) + /// + /// @param request + /// @googleapis_link{google::logging::v2::WriteLogEntriesRequest,google/logging/v2/logging.proto#L160} + /// @param opts Optional. Override the class-level options, such as retry and + /// backoff policies. + /// @return + /// @googleapis_link{google::logging::v2::WriteLogEntriesResponse,google/logging/v2/logging.proto#L241} + /// + /// [google.logging.v2.WriteLogEntriesRequest]: + /// @googleapis_reference_link{google/logging/v2/logging.proto#L160} + /// [google.logging.v2.WriteLogEntriesResponse]: + /// @googleapis_reference_link{google/logging/v2/logging.proto#L241} + /// + future> + AsyncWriteLogEntries( + google::logging::v2::WriteLogEntriesRequest const& request, + Options opts = {}); + private: std::shared_ptr connection_; Options options_; diff --git a/google/cloud/logging/logging_service_v2_connection.cc b/google/cloud/logging/logging_service_v2_connection.cc index 5187b48cae05f..fbce3a88020b3 100644 --- a/google/cloud/logging/logging_service_v2_connection.cc +++ b/google/cloud/logging/logging_service_v2_connection.cc @@ -80,6 +80,14 @@ LoggingServiceV2Connection::AsyncTailLogEntries(ExperimentalTag) { Status(StatusCode::kUnimplemented, "not implemented")); } +future> +LoggingServiceV2Connection::AsyncWriteLogEntries( + google::logging::v2::WriteLogEntriesRequest const&) { + return google::cloud::make_ready_future< + StatusOr>( + Status(StatusCode::kUnimplemented, "not implemented")); +} + std::shared_ptr MakeLoggingServiceV2Connection( Options options) { internal::CheckExpectedOptions> AsyncTailLogEntries(ExperimentalTag); + + virtual future> + AsyncWriteLogEntries( + google::logging::v2::WriteLogEntriesRequest const& request); }; /** diff --git a/google/cloud/logging/mocks/mock_logging_service_v2_connection.h b/google/cloud/logging/mocks/mock_logging_service_v2_connection.h index 85f1f7f05f7d6..fbb3001fece2a 100644 --- a/google/cloud/logging/mocks/mock_logging_service_v2_connection.h +++ b/google/cloud/logging/mocks/mock_logging_service_v2_connection.h @@ -72,6 +72,11 @@ class MockLoggingServiceV2Connection google::logging::v2::TailLogEntriesRequest, google::logging::v2::TailLogEntriesResponse>>), AsyncTailLogEntries, (ExperimentalTag), (override)); + + MOCK_METHOD(future>, + AsyncWriteLogEntries, + (google::logging::v2::WriteLogEntriesRequest const& request), + (override)); }; GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END