Skip to content

Commit 8bb4bde

Browse files
committed
feat: Add custom Protobuf log handler when ABSL is absent
refactor: Switch to version-based Protobuf log handler guards
1 parent 142ffcb commit 8bb4bde

6 files changed

Lines changed: 178 additions & 0 deletions

File tree

cmd/protoc-gen-cpp-tableau-loader/embed/templates/hub.pc.cc.tpl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ void Hub::InitScheduler() {
5353

5454
std::shared_ptr<MessagerMap> Hub::InternalLoad(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */,
5555
std::shared_ptr<const load::Options> options /* = nullptr */) const {
56+
// intercept protobuf error logs
57+
#if TABLEAU_PB_LOG_LEGACY
58+
auto old_handler = google::protobuf::SetLogHandler(util::ProtobufLogHandler);
59+
#else
60+
util::ProtobufAbslLogSink log_sink;
61+
absl::AddLogSink(&log_sink);
62+
#endif
5663
auto msger_map = NewMessagerMap();
5764
options = options ? options : std::make_shared<load::Options>();
5865
for (auto iter : *msger_map) {
@@ -62,11 +69,23 @@ std::shared_ptr<MessagerMap> Hub::InternalLoad(const std::filesystem::path& dir,
6269
bool ok = iter.second->Load(dir, fmt, mopts);
6370
if (!ok) {
6471
ATOM_ERROR("load %s failed: %s", name.c_str(), GetErrMsg().c_str());
72+
// restore to old protobuf log handler
73+
#if TABLEAU_PB_LOG_LEGACY
74+
google::protobuf::SetLogHandler(old_handler);
75+
#else
76+
absl::RemoveLogSink(&log_sink);
77+
#endif
6578
return nullptr;
6679
}
6780
ATOM_DEBUG("loaded %s", name.c_str());
6881
}
6982

83+
// restore to old protobuf log handler
84+
#if TABLEAU_PB_LOG_LEGACY
85+
google::protobuf::SetLogHandler(old_handler);
86+
#else
87+
absl::RemoveLogSink(&log_sink);
88+
#endif
7089
return msger_map;
7190
}
7291

cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,5 +206,51 @@ bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Messag
206206
return true;
207207
}
208208

209+
#if TABLEAU_PB_LOG_LEGACY
210+
// refer: https://github.com/protocolbuffers/protobuf/blob/v3.19.3/src/google/protobuf/stubs/logging.h
211+
void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg) {
212+
#define TABLEAU_PB_LOG_INFO google::protobuf::LOGLEVEL_INFO
213+
#define TABLEAU_PB_LOG_WARNING google::protobuf::LOGLEVEL_WARNING
214+
#define TABLEAU_PB_LOG_ERROR google::protobuf::LOGLEVEL_ERROR
215+
#define TABLEAU_PB_LOG_FATAL google::protobuf::LOGLEVEL_FATAL
216+
#define TABLEAU_PB_LOG_LEVEL level
217+
#define TABLEAU_PB_LOG_FILENAME filename
218+
#define TABLEAU_PB_LOG_LINE line
219+
#define TABLEAU_PB_LOG_MESSAGE msg
220+
#else
221+
// refer: https://github.com/abseil/abseil-cpp/blob/20250512.1/absl/log/log_entry.h
222+
void ProtobufAbslLogSink::Send(const absl::LogEntry& entry) {
223+
#define TABLEAU_PB_LOG_INFO absl::LogSeverity::kInfo
224+
#define TABLEAU_PB_LOG_WARNING absl::LogSeverity::kWarning
225+
#define TABLEAU_PB_LOG_ERROR absl::LogSeverity::kError
226+
#define TABLEAU_PB_LOG_FATAL absl::LogSeverity::kFatal
227+
#define TABLEAU_PB_LOG_LEVEL entry.log_severity()
228+
#define TABLEAU_PB_LOG_FILENAME std::string(entry.source_filename()).c_str()
229+
#define TABLEAU_PB_LOG_LINE entry.source_line()
230+
#define TABLEAU_PB_LOG_MESSAGE std::string(entry.text_message()).c_str()
231+
#endif
232+
233+
static const std::unordered_map<decltype(TABLEAU_PB_LOG_LEVEL), log::Level> kLevelMap = {
234+
{TABLEAU_PB_LOG_INFO, log::kInfo},
235+
{TABLEAU_PB_LOG_WARNING, log::kWarn},
236+
{TABLEAU_PB_LOG_ERROR, log::kError},
237+
{TABLEAU_PB_LOG_FATAL, log::kFatal}};
238+
log::Level lvl = log::kWarn; // default
239+
auto iter = kLevelMap.find(TABLEAU_PB_LOG_LEVEL);
240+
if (iter != kLevelMap.end()) {
241+
lvl = iter->second;
242+
}
243+
ATOM_LOGGER_CALL(tableau::log::DefaultLogger(), lvl, "[libprotobuf %s:%d] %s", TABLEAU_PB_LOG_FILENAME,
244+
TABLEAU_PB_LOG_LINE, TABLEAU_PB_LOG_MESSAGE);
245+
246+
#undef TABLEAU_PB_LOG_INFO
247+
#undef TABLEAU_PB_LOG_WARNING
248+
#undef TABLEAU_PB_LOG_ERROR
249+
#undef TABLEAU_PB_LOG_FATAL
250+
#undef TABLEAU_PB_LOG_LEVEL
251+
#undef TABLEAU_PB_LOG_FILENAME
252+
#undef TABLEAU_PB_LOG_LINE
253+
#undef TABLEAU_PB_LOG_MESSAGE
254+
}
209255
} // namespace util
210256
} // namespace tableau

cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
#pragma once
22
#include <google/protobuf/message.h>
3+
#include <google/protobuf/stubs/common.h>
34

45
#include <chrono>
56
#include <filesystem>
67
#include <string>
78

9+
// Protobuf versions before v4.22.0 (GOOGLE_PROTOBUF_VERSION < 4022000) use the legacy
10+
// logging interface (LogLevel, SetLogHandler). Newer versions removed it in favor of Abseil logging.
11+
#define TABLEAU_PB_LOG_LEGACY (GOOGLE_PROTOBUF_VERSION < 4022000)
12+
13+
#if !TABLEAU_PB_LOG_LEGACY
14+
#include <absl/log/log_entry.h>
15+
#include <absl/log/log_sink.h>
16+
#include <absl/log/log_sink_registry.h>
17+
#endif
18+
819
namespace tableau {
920
const std::string& GetErrMsg();
1021
void SetErrMsg(const std::string& msg);
@@ -57,6 +68,19 @@ const std::string& Format2Ext(Format fmt);
5768
// PatchMessage patches src into dst, which must be a message with the same descriptor.
5869
bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Message& src);
5970

71+
#if TABLEAU_PB_LOG_LEGACY
72+
// ProtobufLogHandler redirects protobuf internal logs to tableau logger.
73+
// Only available for protobuf < v4.22.0, as newer versions removed the old logging interface.
74+
void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg);
75+
#else
76+
// ProtobufAbslLogSink redirects protobuf/Abseil logs to tableau logger.
77+
// For protobuf >= v4.22.0, which uses Abseil logging (absl::LogSink).
78+
class ProtobufAbslLogSink : public absl::LogSink {
79+
public:
80+
void Send(const absl::LogEntry& entry) override;
81+
};
82+
#endif
83+
6084
class TimeProfiler {
6185
protected:
6286
std::chrono::time_point<std::chrono::steady_clock> last_;

test/cpp-tableau-loader/src/protoconf/hub.pc.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ void Hub::InitScheduler() {
5656

5757
std::shared_ptr<MessagerMap> Hub::InternalLoad(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */,
5858
std::shared_ptr<const load::Options> options /* = nullptr */) const {
59+
// intercept protobuf error logs
60+
#if TABLEAU_PB_LOG_LEGACY
61+
auto old_handler = google::protobuf::SetLogHandler(util::ProtobufLogHandler);
62+
#else
63+
util::ProtobufAbslLogSink log_sink;
64+
absl::AddLogSink(&log_sink);
65+
#endif
5966
auto msger_map = NewMessagerMap();
6067
options = options ? options : std::make_shared<load::Options>();
6168
for (auto iter : *msger_map) {
@@ -65,11 +72,23 @@ std::shared_ptr<MessagerMap> Hub::InternalLoad(const std::filesystem::path& dir,
6572
bool ok = iter.second->Load(dir, fmt, mopts);
6673
if (!ok) {
6774
ATOM_ERROR("load %s failed: %s", name.c_str(), GetErrMsg().c_str());
75+
// restore to old protobuf log handler
76+
#if TABLEAU_PB_LOG_LEGACY
77+
google::protobuf::SetLogHandler(old_handler);
78+
#else
79+
absl::RemoveLogSink(&log_sink);
80+
#endif
6881
return nullptr;
6982
}
7083
ATOM_DEBUG("loaded %s", name.c_str());
7184
}
7285

86+
// restore to old protobuf log handler
87+
#if TABLEAU_PB_LOG_LEGACY
88+
google::protobuf::SetLogHandler(old_handler);
89+
#else
90+
absl::RemoveLogSink(&log_sink);
91+
#endif
7392
return msger_map;
7493
}
7594

test/cpp-tableau-loader/src/protoconf/util.pc.cc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,51 @@ bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Messag
211211
return true;
212212
}
213213

214+
#if TABLEAU_PB_LOG_LEGACY
215+
// refer: https://github.com/protocolbuffers/protobuf/blob/v3.19.3/src/google/protobuf/stubs/logging.h
216+
void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg) {
217+
#define TABLEAU_PB_LOG_INFO google::protobuf::LOGLEVEL_INFO
218+
#define TABLEAU_PB_LOG_WARNING google::protobuf::LOGLEVEL_WARNING
219+
#define TABLEAU_PB_LOG_ERROR google::protobuf::LOGLEVEL_ERROR
220+
#define TABLEAU_PB_LOG_FATAL google::protobuf::LOGLEVEL_FATAL
221+
#define TABLEAU_PB_LOG_LEVEL level
222+
#define TABLEAU_PB_LOG_FILENAME filename
223+
#define TABLEAU_PB_LOG_LINE line
224+
#define TABLEAU_PB_LOG_MESSAGE msg
225+
#else
226+
// refer: https://github.com/abseil/abseil-cpp/blob/20250512.1/absl/log/log_entry.h
227+
void ProtobufAbslLogSink::Send(const absl::LogEntry& entry) {
228+
#define TABLEAU_PB_LOG_INFO absl::LogSeverity::kInfo
229+
#define TABLEAU_PB_LOG_WARNING absl::LogSeverity::kWarning
230+
#define TABLEAU_PB_LOG_ERROR absl::LogSeverity::kError
231+
#define TABLEAU_PB_LOG_FATAL absl::LogSeverity::kFatal
232+
#define TABLEAU_PB_LOG_LEVEL entry.log_severity()
233+
#define TABLEAU_PB_LOG_FILENAME std::string(entry.source_filename()).c_str()
234+
#define TABLEAU_PB_LOG_LINE entry.source_line()
235+
#define TABLEAU_PB_LOG_MESSAGE std::string(entry.text_message()).c_str()
236+
#endif
237+
238+
static const std::unordered_map<decltype(TABLEAU_PB_LOG_LEVEL), log::Level> kLevelMap = {
239+
{TABLEAU_PB_LOG_INFO, log::kInfo},
240+
{TABLEAU_PB_LOG_WARNING, log::kWarn},
241+
{TABLEAU_PB_LOG_ERROR, log::kError},
242+
{TABLEAU_PB_LOG_FATAL, log::kFatal}};
243+
log::Level lvl = log::kWarn; // default
244+
auto iter = kLevelMap.find(TABLEAU_PB_LOG_LEVEL);
245+
if (iter != kLevelMap.end()) {
246+
lvl = iter->second;
247+
}
248+
ATOM_LOGGER_CALL(tableau::log::DefaultLogger(), lvl, "[libprotobuf %s:%d] %s", TABLEAU_PB_LOG_FILENAME,
249+
TABLEAU_PB_LOG_LINE, TABLEAU_PB_LOG_MESSAGE);
250+
251+
#undef TABLEAU_PB_LOG_INFO
252+
#undef TABLEAU_PB_LOG_WARNING
253+
#undef TABLEAU_PB_LOG_ERROR
254+
#undef TABLEAU_PB_LOG_FATAL
255+
#undef TABLEAU_PB_LOG_LEVEL
256+
#undef TABLEAU_PB_LOG_FILENAME
257+
#undef TABLEAU_PB_LOG_LINE
258+
#undef TABLEAU_PB_LOG_MESSAGE
259+
}
214260
} // namespace util
215261
} // namespace tableau

test/cpp-tableau-loader/src/protoconf/util.pc.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,22 @@
55

66
#pragma once
77
#include <google/protobuf/message.h>
8+
#include <google/protobuf/stubs/common.h>
89

910
#include <chrono>
1011
#include <filesystem>
1112
#include <string>
1213

14+
// Protobuf versions before v4.22.0 (GOOGLE_PROTOBUF_VERSION < 4022000) use the legacy
15+
// logging interface (LogLevel, SetLogHandler). Newer versions removed it in favor of Abseil logging.
16+
#define TABLEAU_PB_LOG_LEGACY (GOOGLE_PROTOBUF_VERSION < 4022000)
17+
18+
#if !TABLEAU_PB_LOG_LEGACY
19+
#include <absl/log/log_entry.h>
20+
#include <absl/log/log_sink.h>
21+
#include <absl/log/log_sink_registry.h>
22+
#endif
23+
1324
namespace tableau {
1425
const std::string& GetErrMsg();
1526
void SetErrMsg(const std::string& msg);
@@ -62,6 +73,19 @@ const std::string& Format2Ext(Format fmt);
6273
// PatchMessage patches src into dst, which must be a message with the same descriptor.
6374
bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Message& src);
6475

76+
#if TABLEAU_PB_LOG_LEGACY
77+
// ProtobufLogHandler redirects protobuf internal logs to tableau logger.
78+
// Only available for protobuf < v4.22.0, as newer versions removed the old logging interface.
79+
void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg);
80+
#else
81+
// ProtobufAbslLogSink redirects protobuf/Abseil logs to tableau logger.
82+
// For protobuf >= v4.22.0, which uses Abseil logging (absl::LogSink).
83+
class ProtobufAbslLogSink : public absl::LogSink {
84+
public:
85+
void Send(const absl::LogEntry& entry) override;
86+
};
87+
#endif
88+
6589
class TimeProfiler {
6690
protected:
6791
std::chrono::time_point<std::chrono::steady_clock> last_;

0 commit comments

Comments
 (0)