Skip to content

Commit 18073cc

Browse files
feat(bigtable): add logging for result set reader (#15699)
* feat(bigtable): add logging for result set reader * chore: run linter
1 parent 8cc4ad5 commit 18073cc

File tree

6 files changed

+212
-0
lines changed

6 files changed

+212
-0
lines changed

google/cloud/bigtable/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ add_library(
201201
internal/legacy_row_reader.h
202202
internal/logging_data_client.cc
203203
internal/logging_data_client.h
204+
internal/logging_result_set_reader.cc
205+
internal/logging_result_set_reader.h
204206
internal/metrics.cc
205207
internal/metrics.h
206208
internal/mutate_rows_limiter.cc
@@ -484,6 +486,7 @@ if (BUILD_TESTING)
484486
internal/legacy_bulk_mutator_test.cc
485487
internal/legacy_row_reader_test.cc
486488
internal/logging_data_client_test.cc
489+
internal/logging_result_set_reader_test.cc
487490
internal/metrics_test.cc
488491
internal/mutate_rows_limiter_test.cc
489492
internal/operation_context_factory_test.cc

google/cloud/bigtable/bigtable_client_unit_tests.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ bigtable_client_unit_tests = [
6262
"internal/legacy_bulk_mutator_test.cc",
6363
"internal/legacy_row_reader_test.cc",
6464
"internal/logging_data_client_test.cc",
65+
"internal/logging_result_set_reader_test.cc",
6566
"internal/metrics_test.cc",
6667
"internal/mutate_rows_limiter_test.cc",
6768
"internal/operation_context_factory_test.cc",

google/cloud/bigtable/google_cloud_cpp_bigtable.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ google_cloud_cpp_bigtable_hdrs = [
9999
"internal/legacy_async_row_sampler.h",
100100
"internal/legacy_row_reader.h",
101101
"internal/logging_data_client.h",
102+
"internal/logging_result_set_reader.h",
102103
"internal/metrics.h",
103104
"internal/mutate_rows_limiter.h",
104105
"internal/operation_context.h",
@@ -217,6 +218,7 @@ google_cloud_cpp_bigtable_srcs = [
217218
"internal/legacy_async_row_sampler.cc",
218219
"internal/legacy_row_reader.cc",
219220
"internal/logging_data_client.cc",
221+
"internal/logging_result_set_reader.cc",
220222
"internal/metrics.cc",
221223
"internal/mutate_rows_limiter.cc",
222224
"internal/operation_context.cc",
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/bigtable/internal/logging_result_set_reader.h"
16+
#include "google/cloud/internal/debug_string.h"
17+
#include "google/cloud/log.h"
18+
19+
namespace google {
20+
namespace cloud {
21+
namespace bigtable_internal {
22+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
23+
24+
using ::google::cloud::internal::DebugString;
25+
26+
void LoggingResultSetReader::TryCancel() { impl_->TryCancel(); }
27+
28+
bool LoggingResultSetReader::Read(
29+
absl::optional<std::string> const& resume_token,
30+
UnownedPartialResultSet& result) {
31+
if (resume_token) {
32+
GCP_LOG(DEBUG) << __func__ << "() << resume_token=\""
33+
<< DebugString(*resume_token, tracing_options_) << "\"";
34+
} else {
35+
GCP_LOG(DEBUG) << __func__ << "() << (unresumable)";
36+
}
37+
bool success = impl_->Read(resume_token, result);
38+
if (!success) {
39+
GCP_LOG(DEBUG) << __func__ << "() >> (failed)";
40+
} else {
41+
GCP_LOG(DEBUG) << __func__ << "() >> resumption="
42+
<< (result.resumption ? "true" : "false");
43+
}
44+
return success;
45+
}
46+
47+
Status LoggingResultSetReader::Finish() { return impl_->Finish(); }
48+
49+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
50+
} // namespace bigtable_internal
51+
} // namespace cloud
52+
} // namespace google
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_INTERNAL_LOGGING_RESULT_SET_READER_H
16+
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_INTERNAL_LOGGING_RESULT_SET_READER_H
17+
18+
#include "google/cloud/bigtable/internal/partial_result_set_reader.h"
19+
#include "google/cloud/bigtable/version.h"
20+
#include "google/cloud/tracing_options.h"
21+
#include "absl/types/optional.h"
22+
#include <memory>
23+
24+
namespace google {
25+
namespace cloud {
26+
namespace bigtable_internal {
27+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
28+
29+
/**
30+
* A `PartialResultSetReader` decorator that logs the `Read()` `resume_token`
31+
* parameter and the `PartialResultSet::resumption` return value. This is an
32+
* extension to the standard `BigtableLogging` request/response logging.
33+
*/
34+
class LoggingResultSetReader : public PartialResultSetReader {
35+
public:
36+
LoggingResultSetReader(std::unique_ptr<PartialResultSetReader> impl,
37+
TracingOptions tracing_options)
38+
: impl_(std::move(impl)), tracing_options_(std::move(tracing_options)) {}
39+
~LoggingResultSetReader() override = default;
40+
41+
void TryCancel() override;
42+
bool Read(absl::optional<std::string> const& resume_token,
43+
UnownedPartialResultSet& result) override;
44+
Status Finish() override;
45+
46+
private:
47+
std::unique_ptr<PartialResultSetReader> impl_;
48+
TracingOptions tracing_options_;
49+
};
50+
51+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
52+
} // namespace bigtable_internal
53+
} // namespace cloud
54+
} // namespace google
55+
56+
#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_INTERNAL_LOGGING_RESULT_SET_READER_H
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/bigtable/internal/logging_result_set_reader.h"
16+
#include "google/cloud/bigtable/testing/mock_partial_result_set_reader.h"
17+
#include "google/cloud/log.h"
18+
#include "google/cloud/testing_util/scoped_log.h"
19+
#include "google/cloud/testing_util/status_matchers.h"
20+
#include "google/cloud/tracing_options.h"
21+
#include <gmock/gmock.h>
22+
23+
namespace google {
24+
namespace cloud {
25+
namespace bigtable_internal {
26+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
27+
namespace {
28+
29+
using ::testing::_;
30+
using ::testing::AllOf;
31+
using ::testing::Contains;
32+
using ::testing::HasSubstr;
33+
using ::testing::IsEmpty;
34+
using ::testing::StartsWith;
35+
36+
class LoggingResultSetReaderTest : public ::testing::Test {
37+
protected:
38+
testing_util::ScopedLog log_;
39+
};
40+
41+
TEST_F(LoggingResultSetReaderTest, TryCancel) {
42+
auto mock = std::make_unique<bigtable_testing::MockPartialResultSetReader>();
43+
EXPECT_CALL(*mock, TryCancel()).Times(1);
44+
LoggingResultSetReader reader(std::move(mock), TracingOptions{});
45+
reader.TryCancel();
46+
47+
EXPECT_THAT(log_.ExtractLines(), IsEmpty());
48+
}
49+
50+
TEST_F(LoggingResultSetReaderTest, Read) {
51+
auto mock = std::make_unique<bigtable_testing::MockPartialResultSetReader>();
52+
EXPECT_CALL(*mock, Read(_, _))
53+
.WillOnce([](absl::optional<std::string> const&,
54+
UnownedPartialResultSet& result) {
55+
result.resumption = false;
56+
result.result.set_resume_token("test-token");
57+
return true;
58+
})
59+
.WillOnce([] { return false; });
60+
LoggingResultSetReader reader(std::move(mock), TracingOptions{});
61+
google::bigtable::v2::PartialResultSet partial_result_set;
62+
auto result =
63+
UnownedPartialResultSet::FromPartialResultSet(partial_result_set);
64+
ASSERT_TRUE(reader.Read("", result));
65+
EXPECT_EQ("test-token", result.result.resume_token());
66+
67+
auto log_lines = log_.ExtractLines();
68+
EXPECT_THAT(log_lines, AllOf(Contains(StartsWith("Read()"))));
69+
EXPECT_THAT(log_lines, Contains(HasSubstr("resume_token=\"\"")));
70+
EXPECT_THAT(log_lines, Contains(HasSubstr("resumption=false")));
71+
72+
ASSERT_FALSE(reader.Read("test-token", result));
73+
74+
log_lines = log_.ExtractLines();
75+
EXPECT_THAT(log_lines, AllOf(Contains(StartsWith("Read()"))));
76+
EXPECT_THAT(log_lines, Contains(HasSubstr("resume_token=\"test-token\"")));
77+
EXPECT_THAT(log_lines, Contains(HasSubstr("(failed)")));
78+
}
79+
80+
TEST_F(LoggingResultSetReaderTest, Finish) {
81+
Status const expected_status = Status(StatusCode::kOutOfRange, "weird");
82+
auto mock = std::make_unique<bigtable_testing::MockPartialResultSetReader>();
83+
EXPECT_CALL(*mock, Finish()).WillOnce([expected_status] {
84+
return expected_status; // NOLINT(performance-no-automatic-move)
85+
});
86+
LoggingResultSetReader reader(std::move(mock), TracingOptions{});
87+
auto status = reader.Finish();
88+
EXPECT_EQ(expected_status, status);
89+
90+
auto log_lines = log_.ExtractLines();
91+
EXPECT_THAT(log_lines, IsEmpty());
92+
}
93+
94+
} // namespace
95+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
96+
} // namespace bigtable_internal
97+
} // namespace cloud
98+
} // namespace google

0 commit comments

Comments
 (0)