From beffe313e568fc007f9a8037011bbbe797b3f1f1 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 23 Jan 2023 18:57:09 -0800 Subject: [PATCH] GCP Observability Logging: Base64 Encode metadata, message and status-details (#32184) * GCP Observability Logging: Base64 Encode metadata, message and status-details * Use padding for message and status-details --- src/cpp/ext/gcp/observability_logging_sink.cc | 35 ++++++++++++------- .../gcp/observability_logging_sink_test.cc | 16 +++++---- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/cpp/ext/gcp/observability_logging_sink.cc b/src/cpp/ext/gcp/observability_logging_sink.cc index e4baadc59f1..afec33bfc3e 100644 --- a/src/cpp/ext/gcp/observability_logging_sink.cc +++ b/src/cpp/ext/gcp/observability_logging_sink.cc @@ -26,6 +26,8 @@ #include +#include "absl/strings/escaping.h" +#include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/types/optional.h" @@ -34,6 +36,7 @@ #include "google/logging/v2/logging.grpc.pb.h" #include "google/logging/v2/logging.pb.h" +#include #include #include #include @@ -134,8 +137,13 @@ void PayloadToJsonStructProto(LoggingSink::Entry::Payload payload, auto* metadata_proto = (*payload_proto->mutable_fields())["metadata"].mutable_struct_value(); for (auto& metadata : payload.metadata) { - (*metadata_proto->mutable_fields())[metadata.first].set_string_value( - std::move(metadata.second)); + if (absl::EndsWith(metadata.first, "-bin")) { + (*metadata_proto->mutable_fields())[metadata.first].set_string_value( + absl::WebSafeBase64Escape(metadata.second)); + } else { + (*metadata_proto->mutable_fields())[metadata.first].set_string_value( + std::move(metadata.second)); + } } } if (payload.timeout != grpc_core::Duration::Zero()) { @@ -152,7 +160,7 @@ void PayloadToJsonStructProto(LoggingSink::Entry::Payload payload, } if (!payload.status_details.empty()) { (*payload_proto->mutable_fields())["statusDetails"].set_string_value( - std::move(payload.status_details)); + absl::Base64Escape(payload.status_details)); } if (payload.message_length != 0) { (*payload_proto->mutable_fields())["messageLength"].set_number_value( @@ -160,7 +168,7 @@ void PayloadToJsonStructProto(LoggingSink::Entry::Payload payload, } if (!payload.message.empty()) { (*payload_proto->mutable_fields())["message"].set_string_value( - std::move(payload.message)); + absl::Base64Escape(payload.message)); } } @@ -264,14 +272,17 @@ void ObservabilityLoggingSink::LogEntry(Entry entry) { proto_entry->mutable_timestamp()->set_nanos(timespec.tv_nsec); // TODO(yashykt): Check if we need to fill receive timestamp EntryToJsonStructProto(std::move(entry), proto_entry->mutable_json_payload()); - stub_->async()->WriteLogEntries(&(call->context), &(call->request), - &(call->response), [call](Status status) { - if (!status.ok()) { - // TODO(yashykt): Log the contents of the - // request on a failure. - } - delete call; - }); + stub_->async()->WriteLogEntries( + &(call->context), &(call->request), &(call->response), + [call](Status status) { + if (!status.ok()) { + // TODO(yashykt): Log the contents of the + // request on a failure. + gpr_log(GPR_ERROR, "GCP Observability Logging Error %d: %s", + status.error_code(), status.error_message().c_str()); + } + delete call; + }); } ObservabilityLoggingSink::Configuration::Configuration( diff --git a/test/cpp/ext/gcp/observability_logging_sink_test.cc b/test/cpp/ext/gcp/observability_logging_sink_test.cc index 0fb2f2abc67..24ee9cb6a46 100644 --- a/test/cpp/ext/gcp/observability_logging_sink_test.cc +++ b/test/cpp/ext/gcp/observability_logging_sink_test.cc @@ -16,6 +16,8 @@ #include "src/cpp/ext/gcp/observability_logging_sink.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_format.h" #include "gmock/gmock.h" #include "google/protobuf/text_format.h" #include "gtest/gtest.h" @@ -554,7 +556,7 @@ TEST(EntryToJsonStructTest, ClientMessage) { EntryToJsonStructProto(std::move(entry), &proto); std::string output; ::google::protobuf::TextFormat::PrintToString(proto, &output); - const char* pb_str = + std::string pb_str = absl::StrFormat( "fields {\n" " key: \"authority\"\n" " value {\n" @@ -586,7 +588,7 @@ TEST(EntryToJsonStructTest, ClientMessage) { " fields {\n" " key: \"message\"\n" " value {\n" - " string_value: \"hello\"\n" + " string_value: \"%s\"\n" " }\n" " }\n" " fields {\n" @@ -640,7 +642,8 @@ TEST(EntryToJsonStructTest, ClientMessage) { " value {\n" " string_value: \"CLIENT_MESSAGE\"\n" " }\n" - "}\n"; + "}\n", + absl::Base64Escape("hello")); EXPECT_EQ(output, pb_str); } @@ -663,7 +666,7 @@ TEST(EntryToJsonStructTest, ServerMessage) { EntryToJsonStructProto(std::move(entry), &proto); std::string output; ::google::protobuf::TextFormat::PrintToString(proto, &output); - const char* pb_str = + std::string pb_str = absl::StrFormat( "fields {\n" " key: \"authority\"\n" " value {\n" @@ -695,7 +698,7 @@ TEST(EntryToJsonStructTest, ServerMessage) { " fields {\n" " key: \"message\"\n" " value {\n" - " string_value: \"world\"\n" + " string_value: \"%s\"\n" " }\n" " }\n" " fields {\n" @@ -749,7 +752,8 @@ TEST(EntryToJsonStructTest, ServerMessage) { " value {\n" " string_value: \"SERVER_MESSAGE\"\n" " }\n" - "}\n"; + "}\n", + absl::Base64Escape("world")); EXPECT_EQ(output, pb_str); }