From c77285efa096e6e400cacffbcded980d24c5b17f Mon Sep 17 00:00:00 2001 From: Tomoki Nakagawa Date: Sat, 24 Feb 2024 16:19:34 +0000 Subject: [PATCH] Rebase mozc onto Abseil logging library. This is a relatively large update with several breaking changes. - Most of the code in `//base:logging` is now removed. - Logging calls are now handled by `@com_google_absl//absl/log`. This means: - Log message formats will change. - Important: If you have existing log files and run non-release builds (more precisely `!defined(MOZC_NO_LOGGING)`), your files will contain mixed formats after this commit. You may want to remove or rename the existing one. - Flag deprecations - `--colored_log`: they're not supported by Abseil. - `--logtostderr`: this flag had a inconsistent behavior with a google-internal flag of the same name (nor it doesn't make sense for mozc to consolidate the semantics), and is not provided by Abseil. - Note: There's no longer a way to disable log files in debug builds. A configuration option might be added later if this proves problematic. The Abseil logging library is packed with many features. It provides out-of-box integration with the Windows debugger and allows you to adjust the verbosity of your logs using command-line flags (e.g., `--stderrthreshold=0` to see all INFO level logs and above). For a full list of features, take a look at their documentation and source code. PiperOrigin-RevId: 610006013 --- docs/build_mozc_in_docker.md | 7 +- src/android/jni/mozcjni.cc | 1 - src/base/BUILD.bazel | 54 +-- src/base/base.gyp | 3 +- src/base/base_test.gyp | 1 - src/base/init_mozc.cc | 13 +- src/base/log_file.cc | 71 ++++ src/base/log_file.h | 44 +++ src/base/logging.cc | 404 -------------------- src/base/logging.h | 350 ++--------------- src/base/logging_test.cc | 226 ----------- src/base/vlog.cc | 11 + src/build_tools/test_tools/test_launcher.py | 4 +- src/client/client.cc | 1 - src/client/client_stress_test_main.cc | 2 - src/gyp/common.gypi | 1 + src/gyp/common_win.gypi | 1 + src/ios/ios_engine.cc | 7 - src/ios/ios_engine.h | 4 - src/ios/ios_engine_stub.cc | 4 - src/session/session_handler_main.cc | 2 +- src/session/session_test.cc | 4 +- src/unix/ibus/BUILD.bazel | 6 +- src/win32/tip/BUILD.bazel | 1 + src/win32/tip/tip_text_service.cc | 3 +- 25 files changed, 200 insertions(+), 1025 deletions(-) create mode 100644 src/base/log_file.cc create mode 100644 src/base/log_file.h delete mode 100644 src/base/logging.cc delete mode 100644 src/base/logging_test.cc diff --git a/docs/build_mozc_in_docker.md b/docs/build_mozc_in_docker.md index ae7aecd30..9ea3a9393 100644 --- a/docs/build_mozc_in_docker.md +++ b/docs/build_mozc_in_docker.md @@ -128,12 +128,11 @@ bazel test base:util_test --config oss_linux -c dbg ### Output logs to stderr ``` -bazel test base:util_test --config oss_linux --test_arg=--logtostderr --test_output=all +bazel test base:util_test --config oss_linux --test_arg=--stderrthreshold=0 --test_output=all ``` -* The `--test_arg=--logtostderr --test_output=all` flags shows the output of -unitests to stderr. - +* The `--test_arg=--stderrthreshold=0 --test_output=all` flags shows the + output of unitests to stderr. ## Build Mozc on other Linux environment diff --git a/src/android/jni/mozcjni.cc b/src/android/jni/mozcjni.cc index f86c192ec..836c0a21f 100644 --- a/src/android/jni/mozcjni.cc +++ b/src/android/jni/mozcjni.cc @@ -202,7 +202,6 @@ Java_com_google_android_apps_inputmethod_libs_mozc_session_MozcJNI_initialize( return false; } - mozc::Logging::InitLogStream(""); // Android doesn't stream log to a file. return true; } diff --git a/src/base/BUILD.bazel b/src/base/BUILD.bazel index 6226d5242..3205ec0e3 100644 --- a/src/base/BUILD.bazel +++ b/src/base/BUILD.bazel @@ -53,6 +53,7 @@ mozc_cc_library( copts = ["-DMOZC_BUILDTOOL_BUILD"], visibility = ["//:__subpackages__"], deps = [ + ":log_file", ":system_util", "@com_google_absl//absl/flags:flag", ] + mozc_select( @@ -81,6 +82,7 @@ mozc_cc_library( hdrs = ["init_mozc.h"], visibility = ["//:__subpackages__"], deps = [ + ":log_file", "@com_google_absl//absl/flags:flag", ] + mozc_select( android = ["//base"], @@ -128,49 +130,24 @@ mozc_cc_library( mozc_cc_library( name = "logging", - srcs = ["logging.cc"], hdrs = ["logging.h"], - linkopts = mozc_select( - # Android requires linking logging library. - android = ["-llog"], - ), - deps = mozc_select( - default = [ - "@com_google_absl//absl/log", - "@com_google_absl//absl/log:check", - "//base:vlog", - ], - oss = [ - ":clock", - ":const", - ":singleton", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", - ], - wasm = [ - ":clock", - ":const", - ":singleton", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", - ], - ) + [ - "@com_google_absl//absl/flags:flag", - "@com_google_absl//absl/status", - "@com_google_absl//absl/status:statusor", - "@com_google_absl//absl/synchronization", + deps = [ + "@com_google_absl//absl/log", + "@com_google_absl//absl/log:check", ], ) -mozc_cc_test( - name = "logging_test", - size = "small", - srcs = ["logging_test.cc"], - requires_full_emulation = False, +mozc_cc_library( + name = "log_file", + srcs = ["log_file.cc"], + hdrs = ["log_file.h"], deps = [ - ":logging", - "//testing:gunit_main", - "@com_google_absl//absl/strings:str_format", + ":file_stream", + "@com_google_absl//absl/base:core_headers", + "@com_google_absl//absl/log:log_entry", + "@com_google_absl//absl/log:log_sink", + "@com_google_absl//absl/log:log_sink_registry", + "@com_google_absl//absl/synchronization", ], ) @@ -182,6 +159,7 @@ mozc_cc_library( ":logging", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/log:flags", ], ) diff --git a/src/base/base.gyp b/src/base/base.gyp index e9d3c6d65..036c5f2ee 100644 --- a/src/base/base.gyp +++ b/src/base/base.gyp @@ -102,7 +102,7 @@ 'file_stream.cc', 'file_util.cc', 'init_mozc.cc', - 'logging.cc', + 'log_file.cc', 'mmap.cc', 'random.cc', 'strings/unicode.cc', @@ -118,6 +118,7 @@ 'gen_character_set#host', 'hash', 'singleton', + 'absl.gyp:absl_log', 'absl.gyp:absl_random', 'absl.gyp:absl_status', 'absl.gyp:absl_strings', diff --git a/src/base/base_test.gyp b/src/base/base_test.gyp index 307154d6e..5f01302ab 100644 --- a/src/base/base_test.gyp +++ b/src/base/base_test.gyp @@ -104,7 +104,6 @@ 'type': 'executable', 'sources': [ 'container/bitarray_test.cc', - 'logging_test.cc', 'mmap_test.cc', 'random_test.h', 'singleton_test.cc', diff --git a/src/base/init_mozc.cc b/src/base/init_mozc.cc index e8a384dde..55232a9fb 100644 --- a/src/base/init_mozc.cc +++ b/src/base/init_mozc.cc @@ -39,7 +39,7 @@ #include "absl/flags/parse.h" #include "base/file_util.h" -#include "base/logging.h" +#include "base/log_file.h" #ifndef MOZC_BUILDTOOL_BUILD #include "base/system_util.h" @@ -52,6 +52,15 @@ ABSL_FLAG(std::string, log_dir, "", "If specified, logfiles are written into this directory " "instead of the default logging directory."); +ABSL_RETIRED_FLAG( + bool, logtostderr, false, + "[Deprecated; no-op] Log messages only go to stderr, not log files."); + +ABSL_RETIRED_FLAG( + bool, colored_log, true, + "[Deprecated; no-op] Enables colored log messages on tty devices"); + + ABSL_FLAG(std::string, program_invocation_name, "", "Program name copied from argv[0]."); @@ -107,7 +116,7 @@ void InitMozc(const char *arg0, int *argc, char ***argv) { ParseCommandLineFlags(*argc, *argv); const std::string program_name = *argc > 0 ? (*argv)[0] : "UNKNOWN"; - Logging::InitLogStream(GetLogFilePathFromProgramName(program_name)); + RegisterLogFileSink(GetLogFilePathFromProgramName(program_name)); } } // namespace mozc diff --git a/src/base/log_file.cc b/src/base/log_file.cc new file mode 100644 index 000000000..4034bef88 --- /dev/null +++ b/src/base/log_file.cc @@ -0,0 +1,71 @@ +// Copyright 2010-2021, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/log_file.h" + +#include + +#include "absl/base/thread_annotations.h" +#include "absl/log/log_entry.h" +#include "absl/log/log_sink.h" +#include "absl/log/log_sink_registry.h" +#include "absl/synchronization/mutex.h" +#include "base/file_stream.h" + +namespace mozc { +namespace { + +class LogFileSink : public absl::LogSink { + public: + explicit LogFileSink(const std::string &path) : file_(path) {} + + void Send(const absl::LogEntry &entry) override { + absl::MutexLock lock(&mutex_); + file_ << entry.text_message_with_prefix(); + } + + void Flush() override { + absl::MutexLock lock(&mutex_); + file_.flush(); + } + + private: + absl::Mutex mutex_; + OutputFileStream file_ ABSL_GUARDED_BY(mutex_); +}; + +} // namespace + +void RegisterLogFileSink(const std::string &path) { +#if !defined(MOZC_NO_LOGGING) && !defined(__ANDROID__) + absl::AddLogSink(new LogFileSink(path)); +#endif // !MOZC_NO_LOGGING && !__ANDROID__ +} + +} // namespace mozc diff --git a/src/base/log_file.h b/src/base/log_file.h new file mode 100644 index 000000000..1d0833dcc --- /dev/null +++ b/src/base/log_file.h @@ -0,0 +1,44 @@ +// Copyright 2010-2021, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef MOZC_BASE_LOG_FILE_H_ +#define MOZC_BASE_LOG_FILE_H_ + +#include + +namespace mozc { + +// Registers an `absl::LogSink` tied to a file at `path`. +// +// This function becomes no-op when MOZC_NO_LOGGING or __ANDROID__ is defined. +void RegisterLogFileSink(const std::string &path); + +} // namespace mozc + +#endif // MOZC_BASE_LOG_FILE_H_ diff --git a/src/base/logging.cc b/src/base/logging.cc deleted file mode 100644 index 15079d9a0..000000000 --- a/src/base/logging.cc +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright 2010-2021, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "base/logging.h" - -#ifdef __ANDROID__ -#include -#endif // __ANDROID__ - -#ifdef _WIN32 -#define NO_MINMAX -#include -#else // _WIN32 -#include -#include -#endif // _WIN32 - -#include -#ifdef _WIN32 -#include -#endif // _WIN32 -#include -#include -#include -#ifdef _WIN32 -#include -#endif // _WIN32 -#include -#include -#include - -#ifdef __ANDROID__ -#include "base/const.h" -#endif // __ANDROID__ -#include "absl/flags/flag.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" -#include "base/clock.h" -#include "base/singleton.h" - -ABSL_FLAG(bool, colored_log, true, - "Enables colored log messages on tty devices"); -ABSL_FLAG(bool, logtostderr, false, - "log messages go to stderr instead of logfiles") - .OnUpdate([] { - mozc::Logging::SetLogToStderr(absl::GetFlag(FLAGS_logtostderr)); - }); - -namespace mozc { - -#ifdef __ANDROID__ -namespace { -// In order to make logging.h independent from , we use the -// raw number to define the following constants. Check the equality here -// just in case. -#define COMPARE_LOG_LEVEL(mozc_log_level, android_log_level) \ - static_assert( \ - static_cast(mozc_log_level) == static_cast(android_log_level), \ - "Checking Android log level constants.") -COMPARE_LOG_LEVEL(LOG_UNKNOWN, ANDROID_LOG_UNKNOWN); -COMPARE_LOG_LEVEL(LOG_DEFAULT, ANDROID_LOG_DEFAULT); -COMPARE_LOG_LEVEL(LOG_VERBOSE, ANDROID_LOG_VERBOSE); -COMPARE_LOG_LEVEL(LOG_DEBUG, ANDROID_LOG_DEBUG); -COMPARE_LOG_LEVEL(LOG_INFO, ANDROID_LOG_INFO); -COMPARE_LOG_LEVEL(LOG_WARNING, ANDROID_LOG_WARN); -COMPARE_LOG_LEVEL(LOG_ERROR, ANDROID_LOG_ERROR); -COMPARE_LOG_LEVEL(LOG_FATAL, ANDROID_LOG_FATAL); -COMPARE_LOG_LEVEL(LOG_SILENT, ANDROID_LOG_SILENT); -#undef COMPARE_LOG_LEVEL -} // namespace -#endif // __ANDROID__ - -// Use the same implementation both for Opt and Debug. -std::string Logging::GetLogMessageHeader() { -#ifdef __ANDROID__ - // On Android, other records are not needed because they are added by - // Android's logging framework. - return absl::StrCat(pthread_self(), " "); // returns unsigned long. - -#else // __ANDROID__ - - const absl::Time at = Clock::GetAbslTime(); - const absl::TimeZone tz = Clock::GetTimeZone(); - const std::string timestamp = absl::FormatTime("%Y-%m-%d %H:%M:%S ", at, tz); - -#if defined(__wasm__) - return absl::StrCat(timestamp, ::getpid(), " ", - static_cast(pthread_self())); -#elif defined(__linux__) - return absl::StrCat(timestamp, ::getpid(), " ", - // It returns unsigned long. - pthread_self()); -#elif defined(__APPLE__) -#ifdef __LP64__ - return absl::StrCat(timestamp, ::getpid(), " ", - reinterpret_cast(pthread_self())); -#else // __LP64__ - return absl::StrCat(timestamp, ::getpid(), " ", ::getpid(), - reinterpret_cast(pthread_self())); -#endif // __LP64__ -#elif defined(_WIN32) - return absl::StrCat(timestamp, ::GetCurrentProcessId(), " ", - ::GetCurrentThreadId()); -#endif // _WIN32 -#endif // __ANDROID__ -} - -#ifdef MOZC_NO_LOGGING - -void Logging::InitLogStream(const std::string &log_file_path) {} - -void Logging::CloseLogStream() {} - -WorkingLogStream &Logging::GetWorkingLogStream() { - // Never called. - return *(new WorkingLogStream); -} - -void Logging::FinalizeWorkingLogStream(LogSeverity severity, - WorkingLogStream *working_stream) { - // Never called. - delete working_stream; -} - -NullLogStream &Logging::GetNullLogStream() { - return *(Singleton::get()); -} - -const char *Logging::GetLogSeverityName(LogSeverity severity) { return ""; } - -const char *Logging::GetBeginColorEscapeSequence(LogSeverity severity) { - return ""; -} - -const char *Logging::GetEndColorEscapeSequence() { return ""; } - -void Logging::SetLogToStderr(bool log_to_stderr) {} - -#else // MOZC_NO_LOGGING - -namespace { - -class LogStreamImpl { - public: - LogStreamImpl(); - ~LogStreamImpl(); - - void Init(const std::string &log_file_path); - void Reset(); - - bool support_color() const { return support_color_; } - - void Write(LogSeverity, const std::string &log); - void set_log_to_stderr(bool log_to_stderr) { -#if defined(__ANDROID__) - // Android uses Android's log library. - use_cerr_ = false; -#else // __ANDROID__ - absl::MutexLock l(&mutex_); - use_cerr_ = log_to_stderr; -#endif // !__ANDROID__ - } - - private: - void ResetUnlocked(); - - // Real backing log stream. - // This is not thread-safe so must be guarded. - // If std::cerr is real log stream, this is empty. - std::unique_ptr real_log_stream_; - bool support_color_ = false; - bool use_cerr_ = false; - absl::Mutex mutex_; -}; - -void LogStreamImpl::Write(LogSeverity severity, const std::string &log) { - absl::MutexLock l(&mutex_); - if (use_cerr_) { - std::cerr << log; - } else { -#if defined(__ANDROID__) - __android_log_write(severity, kProductPrefix, - const_cast(log.c_str())); -#else // __ANDROID__ - // Since our logging mechanism is essentially singleton, it is indeed - // possible that this method is called before |Logging::InitLogStream()|. - // b/32360767 is an example, where |SystemUtil::GetLoggingDirectory()| - // called as a preparation for |Logging::InitLogStream()| internally - // triggered |LOG(ERROR)|. - if (real_log_stream_) { - *real_log_stream_ << log; - real_log_stream_->flush(); - } -#endif // !__ANDROID__ - } -} - -LogStreamImpl::LogStreamImpl() { Reset(); } - -// Initializes real log stream. -// After initialization, use_cerr_ and real_log_stream_ become like following: -// OS, --logtostderr => use_cerr_, real_log_stream_ -// Android, * => false, empty -// Others, true => true, empty -// Others, false => true, initialized -void LogStreamImpl::Init(const std::string &log_file_path) { - absl::MutexLock l(&mutex_); - ResetUnlocked(); - - if (use_cerr_) { - return; - } -#if defined(_WIN32) - // On Windows, just create a stream. - // Since Windows uses UTF-16 for internationalized file names, we should - // convert the encoding of the given |log_file_path| from UTF-8 to UTF-16. - // NOTE: To avoid circular dependency, |Util::Utf8ToWide| shouldn't be used - // here. - DCHECK_NE(log_file_path.size(), 0); - std::wstring_convert, wchar_t> utf8_to_wide; - real_log_stream_ = std::make_unique( - utf8_to_wide.from_bytes(log_file_path).c_str(), std::ios::app); -#elif !defined(__ANDROID__) - // On non-Android platform, change file mode in addition. - // Android uses logcat instead of log file. - DCHECK_NE(log_file_path.size(), 0); - real_log_stream_ = - std::make_unique(log_file_path.c_str(), std::ios::app); - ::chmod(log_file_path.c_str(), 0600); -#endif // !(_WIN32 ||__ANDROID__) - DCHECK(!use_cerr_ || !real_log_stream_); -} - -void LogStreamImpl::Reset() { - absl::MutexLock l(&mutex_); - ResetUnlocked(); -} - -void LogStreamImpl::ResetUnlocked() { - real_log_stream_.reset(); -#if defined(__ANDROID__) || defined(_WIN32) - // On Android, the standard log library is used. - // On Windows, coloring is disabled - // because cmd.exe doesn't support ANSI color escape sequences. - // TODO(team): Considers to use SetConsoleTextAttribute on Windows. - support_color_ = false; -#else // __ANDROID__, _WIN32 - support_color_ = (use_cerr_ && absl::GetFlag(FLAGS_colored_log) && - ::isatty(::fileno(stderr))); -#endif // !(__ANDROID__ || _WIN32) - // use_cerr_ is updated by ABSL_FLAG.OnUpdate(). -} - -LogStreamImpl::~LogStreamImpl() { Reset(); } -} // namespace - -void Logging::InitLogStream(const std::string &log_file_path) { - Singleton::get()->Init(log_file_path); - WorkingLogStream &stream = GetWorkingLogStream(); - stream << "Log file created at: " << Logging::GetLogMessageHeader(); - FinalizeWorkingLogStream(LogSeverity::LOG_INFO, &stream); -} - -void Logging::CloseLogStream() { Singleton::get()->Reset(); } - -WorkingLogStream &Logging::GetWorkingLogStream() { - return *(new WorkingLogStream); -} - -void Logging::FinalizeWorkingLogStream(LogSeverity severity, - WorkingLogStream *working_stream) { - *working_stream << std::endl; - Singleton::get()->Write(severity, working_stream->str()); - // The working stream is new'd in LogStreamImpl::GetWorkingLogStream(). - // Must be deleted by finalizer. - delete working_stream; -} - -NullLogStream &Logging::GetNullLogStream() { - return *(Singleton::get()); -} - -namespace { -// ANSI Color escape sequences. -// FYI: Other escape sequences are here. -// Black: "\x1b[30m" -// Green "\x1b[32m" -// Blue: "\x1b[34m" -// Magenta: "\x1b[35m" -// White "\x1b[37m" -constexpr const char kClearEscapeSequence[] = "\x1b[0m"; -constexpr const char kRedEscapeSequence[] = "\x1b[31m"; -constexpr const char kYellowEscapeSequence[] = "\x1b[33m"; -constexpr const char kCyanEscapeSequence[] = "\x1b[36m"; - -constexpr struct SeverityProperty { - public: - const char *label; - const char *color_escape_sequence; -} kSeverityProperties[] = { -#ifdef __ANDROID__ - {"UNKNOWN", kCyanEscapeSequence}, {"DEFAULT", kCyanEscapeSequence}, - {"VERBOSE", kCyanEscapeSequence}, {"DEBUG", kCyanEscapeSequence}, - {"INFO", kCyanEscapeSequence}, {"WARNING", kYellowEscapeSequence}, - {"ERROR", kRedEscapeSequence}, {"FATAL", kRedEscapeSequence}, - {"SILENT", kCyanEscapeSequence}, -#else // __ANDROID__ - {"INFO", kCyanEscapeSequence}, - {"WARNING", kYellowEscapeSequence}, - {"ERROR", kRedEscapeSequence}, - {"FATAL", kRedEscapeSequence}, -#endif // !__ANDROID__ -}; -} // namespace - -const char *Logging::GetLogSeverityName(LogSeverity severity) { - return kSeverityProperties[severity].label; -} - -const char *Logging::GetBeginColorEscapeSequence(LogSeverity severity) { - if (Singleton::get()->support_color()) { - return kSeverityProperties[severity].color_escape_sequence; - } - return ""; -} - -const char *Logging::GetEndColorEscapeSequence() { - if (Singleton::get()->support_color()) { - return kClearEscapeSequence; - } - return ""; -} - -void Logging::SetLogToStderr(bool log_to_stderr) { - Singleton::get()->set_log_to_stderr(log_to_stderr); -} -#endif // !MOZC_NO_LOGGING - -LogFinalizer::LogFinalizer(LogSeverity severity) : severity_(severity) {} - -LogFinalizer::~LogFinalizer() { - Logging::FinalizeWorkingLogStream(severity_, working_stream_); - if (severity_ >= LOG_FATAL) { - // On windows, call exception handler to - // make stack trace and minidump -#ifdef _WIN32 - ::RaiseException(::GetLastError(), EXCEPTION_NONCONTINUABLE, 0, nullptr); -#else // _WIN32 - mozc::Logging::CloseLogStream(); - exit(-1); -#endif // !_WIN32 - } -} - -void WorkingLogStream::Append(size_t count, const char ch) { - while (count-- > 0) { - os_.put(ch); - } -} - -void WorkingLogStream::Append(const absl::string_view v) { - os_.write(v.data(), v.size()); -} - -void LogFinalizer::operator&(WorkingLogStream &working_stream) { - working_stream_ = &working_stream; -} - -void NullLogFinalizer::OnFatal() { -#ifdef _WIN32 - ::RaiseException(::GetLastError(), EXCEPTION_NONCONTINUABLE, 0, nullptr); -#else // _WIN32 - exit(-1); -#endif // !_WIN32 -} - -} // namespace mozc diff --git a/src/base/logging.h b/src/base/logging.h index 5c63b2147..808787493 100644 --- a/src/base/logging.h +++ b/src/base/logging.h @@ -30,335 +30,37 @@ #ifndef MOZC_BASE_LOGGING_H_ #define MOZC_BASE_LOGGING_H_ -#include +// These includes are kept for legacy reasons. Prefer including them directly, +// unless you use DFATAL severity backported below. +#include "absl/log/check.h" // IWYU pragma: keep +#include "absl/log/log.h" // IWYU pragma: keep - -#include -#include -#include - -#include "absl/flags/declare.h" -#include "absl/flags/flag.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" - -ABSL_DECLARE_FLAG(bool, logtostderr); - -namespace mozc { - -enum LogSeverity { -#ifdef __ANDROID__ - // Defined in - LOG_UNKNOWN = 0, // ANDROID_LOG_UNKNOWN - LOG_DEFAULT = 1, // ANDROID_LOG_DEFAULT - LOG_VERBOSE = 2, // ANDROID_LOG_VERBOSE - LOG_DEBUG = 3, // ANDROID_LOG_DEBUG - LOG_INFO = 4, // ANDROID_LOG_INFO - LOG_WARNING = 5, // ANDROID_LOG_WARN - LOG_ERROR = 6, // ANDROID_LOG_ERROR - LOG_FATAL = 7, // ANDROID_LOG_FATAL - LOG_SILENT = 8, // ANDROID_LOG_SILENT - LOG_SEVERITY_SIZE = 9, -#else // __ANDROID__ - LOG_INFO = 0, - LOG_WARNING = 1, - LOG_ERROR = 2, -// Special hack for Windows build, where ERROR is defined as 0 in wingdi.h. -#ifdef _WIN32 - LOG_0 = LOG_ERROR, -#endif // _WIN32 - LOG_FATAL = 3, - LOG_SEVERITY_SIZE = 4, -#endif // !__ANDROID__ -}; - -// DFATAL is FATAL in debug mode, ERROR in normal mode +// Note that abseil HEAD has ABSL_LTS_RELEASE_VERSION undefined. +#if defined(ABSL_LTS_RELEASE_VERSION) && ABSL_LTS_RELEASE_VERSION < 20240116 +// Older version of abseil doesn't ship with DFATAL. This is a very hacky +// backport that needs to be removed as soon as we migrate to Abseil LTS +// 20240116. #ifdef DEBUG -#define LOG_DFATAL LOG_FATAL +#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \ + ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) + +namespace absl { +ABSL_NAMESPACE_BEGIN +static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kFatal; +ABSL_NAMESPACE_END +} // namespace absl #else // DEBUG -#define LOG_DFATAL LOG_ERROR +#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \ + ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) + +namespace absl { +ABSL_NAMESPACE_BEGIN +static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kError; +ABSL_NAMESPACE_END +} // namespace absl #endif // !DEBUG +#endif // ABSL_LTS_RELEASE_VERSION < 20240116 -class WorkingLogStream; -class NullLogStream; - -class Logging { - public: - Logging() = delete; - Logging(const Logging &) = delete; - Logging &operator=(const Logging &) = delete; - // Initializes log stream with the output file path and --logtostderr. - static void InitLogStream(const std::string &log_file_path); - - // Closes the logging stream - static void CloseLogStream(); - - // Gets working log stream. The log message can be written to the stream. - // The stream must be finalized by FinalizeWorkingLogStream(). - static WorkingLogStream &GetWorkingLogStream(); - - // Finalizes the working stream. - // - Appends std::endl to working stream. - // - Writes the content to real backing logging stream, which is initialized - // by InitLogStream(). - // - Deletes the working stream object. - static void FinalizeWorkingLogStream(LogSeverity, WorkingLogStream *); - - // Gets NullLogStream for MOZC_NO_LOGGING mode - static NullLogStream &GetNullLogStream(); - - // Converts LogSeverity to the string name - static const char *GetLogSeverityName(LogSeverity severity); - - // Returns "YYYY-MM-DD HH:MM:SS PID TID", e.g. "2008 11-16 19:40:21 100 20" - static std::string GetLogMessageHeader(); - - // Gets an escape sequence to colorize log messages on tty devices. - static const char *GetBeginColorEscapeSequence(LogSeverity severity); - static const char *GetEndColorEscapeSequence(); - - static void SetLogToStderr(bool log_to_stderr); -}; - -namespace logging_internal { - -// Based on -// https://github.com/abseil/abseil-cpp/blob/master/absl/strings/internal/has_absl_stringify.h -// -// This can be removed once Abseil LTS supports `absl::HasAbslStringify`. -template -struct HasAbslStringify : std::false_type {}; - -template -struct HasAbslStringify< - T, std::void_t(), - std::declval()))>> - : std::true_type {}; - -} // namespace logging_internal - -// WorkingLogStream is a std::ostringstream that also implements Abseil's Sink. -class WorkingLogStream { - public: - WorkingLogStream() = default; - - // Sink methods. - // https://github.com/abseil/abseil-cpp/blob/master/absl/strings/internal/stringify_sink.h - void Append(size_t count, char ch); - void Append(absl::string_view v); - friend void AbslFormatFlush(WorkingLogStream *sink, absl::string_view v) { - sink->Append(v); - } - - template ::value, - std::nullptr_t> = nullptr> - WorkingLogStream &operator<<(const T &v) { - AbslStringify(*this, v); - return *this; - } - template ::value, - std::nullptr_t> = nullptr> - WorkingLogStream &operator<<(const T &v) { - os_ << v; - return *this; - } - WorkingLogStream &operator<<(std::ostream &(*func)(std::ostream &)) { - os_ << func; - return *this; - } - - std::string str() const { return os_.str(); } - - private: - std::ostringstream os_; -}; - -// Finalizer to flush/delete working log stream. -// Finalizer takes woking log stream instance through operator&() -// and finalizes it in destructor. -class LogFinalizer { - public: - explicit LogFinalizer(LogSeverity severity); - ~LogFinalizer(); - - void operator&(WorkingLogStream &); - - private: - const LogSeverity severity_; - WorkingLogStream *working_stream_; -}; - -// When using NullLogStream, all debug message will be stripped -class NullLogStream { - public: - template - NullLogStream &operator<<(const T &value) { - return *this; - } - NullLogStream &operator<<(std::ostream &(*pfunc)(std::ostream &)) { - return *this; - } -}; - -class NullLogFinalizer { - public: - explicit NullLogFinalizer(LogSeverity severity) : severity_(severity) {} - - ~NullLogFinalizer() { - if (severity_ >= LOG_FATAL) { - OnFatal(); - } - } - - void operator&(NullLogStream &) {} - - private: - static void OnFatal(); - - const LogSeverity severity_; -}; - -} // namespace mozc - -// ad-hoc porting of google-glog -#ifdef MOZC_NO_LOGGING // don't use logging feature. - -// in release binary, we don't want to evaluate the outputs for logging. -// LOG(FATAL) is an exception. -#define LOG(severity) \ - (mozc::LOG_##severity < mozc::LOG_FATAL) \ - ? (void)0 \ - : mozc::NullLogFinalizer(mozc::LOG_##severity) & \ - mozc::Logging::GetNullLogStream() - -// To suppress the "statement has no effect" waring, (void) is -// inserted. This technique is suggested by the gcc manual -// -Wunused-variable section. -#define LOG_IF(severity, condition) \ - (mozc::LOG_##severity < mozc::LOG_FATAL || !(condition)) \ - ? (void)0 \ - : mozc::NullLogFinalizer(mozc::LOG_##severity) & \ - mozc::Logging::GetNullLogStream() - -#define CHECK(condition) \ - (condition) ? (void)0 \ - : mozc::NullLogFinalizer(mozc::LOG_FATAL) & \ - mozc::Logging::GetNullLogStream() - -#else // MOZC_NO_LOGGING - -#define LOG(severity) \ - mozc::LogFinalizer(mozc::LOG_##severity) & \ - mozc::Logging::GetWorkingLogStream() \ - << mozc::Logging::GetLogMessageHeader() << " " << __FILE__ << "(" \ - << __LINE__ << ") " \ - << mozc::Logging::GetBeginColorEscapeSequence(mozc::LOG_##severity) \ - << "LOG(" << mozc::Logging::GetLogSeverityName(mozc::LOG_##severity) \ - << ")" << mozc::Logging::GetEndColorEscapeSequence() << " " - -#define LOG_IF(severity, condition) \ - (!(condition)) \ - ? (void)0 \ - : mozc::LogFinalizer(mozc::LOG_##severity) & \ - mozc::Logging::GetWorkingLogStream() \ - << mozc::Logging::GetLogMessageHeader() << " " << __FILE__ \ - << "(" << __LINE__ << ") " \ - << mozc::Logging::GetBeginColorEscapeSequence( \ - mozc::LOG_##severity) \ - << "LOG(" \ - << mozc::Logging::GetLogSeverityName(mozc::LOG_##severity) \ - << ")" << mozc::Logging::GetEndColorEscapeSequence() << " [" \ - << #condition << "] " - -#define CHECK(condition) \ - (condition) \ - ? (void)0 \ - : mozc::LogFinalizer(mozc::LOG_FATAL) & \ - mozc::Logging::GetWorkingLogStream() \ - << mozc::Logging::GetLogMessageHeader() << " " << __FILE__ \ - << "(" << __LINE__ << ") " \ - << mozc::Logging::GetBeginColorEscapeSequence(mozc::LOG_FATAL) \ - << "CHECK" << mozc::Logging::GetEndColorEscapeSequence() \ - << " [" << #condition << "] " -#endif // !MOZC_NO_LOGGING - -#define CHECK_EQ(a, b) CHECK((a) == (b)) -#define CHECK_NE(a, b) CHECK((a) != (b)) -#define CHECK_GE(a, b) CHECK((a) >= (b)) -#define CHECK_LE(a, b) CHECK((a) <= (b)) -#define CHECK_GT(a, b) CHECK((a) > (b)) -#define CHECK_LT(a, b) CHECK((a) < (b)) - -// Debug build -#if defined(DEBUG) || defined(_DEBUG) - -#define DLOG(severity) LOG(severity) -#define DLOG_IF(severity, condition) LOG_IF(severity, condition) -#define DCHECK(condition) CHECK(condition) -#define DCHECK_EQ(a, b) CHECK_EQ(a, b) -#define DCHECK_NE(a, b) CHECK_NE(a, b) -#define DCHECK_GE(a, b) CHECK_GE(a, b) -#define DCHECK_LE(a, b) CHECK_LE(a, b) -#define DCHECK_GT(a, b) CHECK_GT(a, b) -#define DCHECK_LT(a, b) CHECK_LT(a, b) - -#else // opt build - -#define DLOG(severity) \ - mozc::NullLogFinalizer(mozc::LOG_##severity) & \ - mozc::Logging::GetNullLogStream() - -#define DLOG_IF(severity, condition) \ - (true || !(condition)) ? (void)0 \ - : mozc::NullLogFinalizer(mozc::LOG_##severity) & \ - mozc::Logging::GetNullLogStream() - -#define DCHECK(condition) \ - while (false) CHECK(condition) -#define DCHECK_EQ(a, b) \ - while (false) CHECK_EQ(a, b) -#define DCHECK_NE(a, b) \ - while (false) CHECK_NE(a, b) -#define DCHECK_GE(a, b) \ - while (false) CHECK_GE(a, b) -#define DCHECK_LE(a, b) \ - while (false) CHECK_LE(a, b) -#define DCHECK_GT(a, b) \ - while (false) CHECK_GT(a, b) -#define DCHECK_LT(a, b) \ - while (false) CHECK_LT(a, b) - -#endif // opt build - -#ifndef MOZC_LOG_PROTOBUF #define MOZC_LOG_PROTOBUF(message) ((message).DebugString()) -#endif // MOZC_LOG_PROTOBUF - -// CHECK_OK and DCHECK_OK -namespace mozc::status_internal { - -template -inline const absl::Status &AsStatus(const absl::StatusOr &status_or) { - return status_or.status(); -} - -inline const absl::Status &AsStatus(const absl::Status &status) { - return status; -} - -} // namespace mozc::status_internal - -#define CHECK_OK(val) \ - CHECK_EQ(absl::OkStatus(), ::mozc::status_internal::AsStatus(val)) -#define DCHECK_OK(val) \ - DCHECK_EQ(absl::OkStatus(), ::mozc::status_internal::AsStatus(val)) - - -#ifndef MOZC_LOG_PROTOBUF -#define MOZC_LOG_PROTOBUF(message) (message) -#endif // !MOZC_LOG_PROTOBUF #endif // MOZC_BASE_LOGGING_H_ diff --git a/src/base/logging_test.cc b/src/base/logging_test.cc deleted file mode 100644 index 89c125abb..000000000 --- a/src/base/logging_test.cc +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2010-2021, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "base/logging.h" - -#include - -#include "absl/strings/str_format.h" -#include "testing/gunit.h" - -namespace mozc { -namespace { - -TEST(LoggingTest, CompileTest) { - if (false) { - LOG(INFO) << ""; - LOG(WARNING) << ""; - LOG(ERROR) << ""; - LOG(DFATAL) << ""; - LOG(FATAL) << ""; - } - if (false) { - DLOG(INFO) << ""; - DLOG(WARNING) << ""; - DLOG(ERROR) << ""; - DLOG(FATAL) << ""; - } - - LOG_IF(INFO, false) << ""; - LOG_IF(WARNING, false) << ""; - LOG_IF(ERROR, false) << ""; - LOG_IF(DFATAL, false) << ""; - LOG_IF(FATAL, false) << ""; - - DLOG_IF(INFO, false) << ""; - DLOG_IF(WARNING, false) << ""; - DLOG_IF(ERROR, false) << ""; - DLOG_IF(FATAL, false) << ""; - - CHECK(true) << ""; - CHECK_EQ(true, true) << ""; - CHECK_NE(true, false) << ""; - CHECK_GE(2, 1) << ""; - CHECK_GE(1, 1) << ""; - CHECK_LE(1, 2) << ""; - CHECK_LE(1, 1) << ""; - CHECK_GT(2, 1) << ""; - CHECK_LT(1, 2) << ""; - - DCHECK(true) << ""; - DCHECK_EQ(true, true) << ""; - DCHECK_NE(true, false) << ""; - DCHECK_GE(2, 1) << ""; - DCHECK_GE(1, 1) << ""; - DCHECK_LE(1, 2) << ""; - DCHECK_LE(1, 1) << ""; - DCHECK_GT(2, 1) << ""; - DCHECK_LT(1, 2) << ""; -} - -TEST(LoggingTest, SideEffectTest) { - bool flag = false; - -#ifdef MOZC_NO_LOGGING - // LOG_(INFO|WARNING|ERROR|DFATAL) are not executed on release mode - flag = true; - LOG_IF(INFO, flag = false) << ""; - EXPECT_TRUE(flag); - - flag = true; - LOG_IF(WARNING, flag = false) << ""; - EXPECT_TRUE(flag); - - flag = true; - LOG_IF(ERROR, flag = false) << ""; - EXPECT_TRUE(flag); - - flag = true; - LOG_IF(DFATAL, flag = false) << ""; - EXPECT_TRUE(flag); -#else // MOZC_NO_LOGGING - flag = true; - LOG_IF(INFO, flag = false) << ""; - EXPECT_FALSE(flag); - - flag = true; - LOG_IF(WARNING, flag = false) << ""; - EXPECT_FALSE(flag); - - flag = true; - LOG_IF(ERROR, flag = false) << ""; - EXPECT_FALSE(flag); - - flag = true; - LOG_IF(DFATAL, flag = false) << ""; - EXPECT_FALSE(flag); -#endif // !MOZC_NO_LOGGING - - flag = true; - LOG_IF(FATAL, flag = false) << ""; - EXPECT_FALSE(flag); - - flag = false; - CHECK(flag = true) << ""; - EXPECT_TRUE(flag); - - flag = false; - CHECK_EQ(true, flag = true) << ""; - EXPECT_TRUE(flag); - - flag = false; - CHECK_NE(false, flag = true) << ""; - EXPECT_TRUE(flag); - - int i = 0; - - i = 10; - CHECK_GE(20, i = 11) << ""; - EXPECT_EQ(i, 11); - - i = 10; - CHECK_GT(20, i = 11) << ""; - EXPECT_EQ(i, 11); - - i = 10; - CHECK_LE(1, i = 11) << ""; - EXPECT_EQ(i, 11); - - i = 10; - CHECK_LT(1, i = 11) << ""; - EXPECT_EQ(i, 11); -} - -namespace { -int g_counter = 0; -std::string DebugString() { - ++g_counter; - std::ostringstream os; - os << g_counter << " test!"; - return os.str(); -} -} // namespace - -TEST(LoggingTest, RightHandSideEvaluation) { - g_counter = 0; - LOG(INFO) << "test: " << DebugString(); - LOG(ERROR) << "test: " << DebugString(); - LOG(WARNING) << "test: " << DebugString(); - -#ifdef MOZC_NO_LOGGING - EXPECT_EQ(g_counter, 0); -#else // MOZC_NO_LOGGING - EXPECT_EQ(g_counter, 3); -#endif // !MOZC_NO_LOGGING - - g_counter = 0; - LOG_IF(INFO, true) << "test: " << DebugString(); - LOG_IF(ERROR, true) << "test: " << DebugString(); - LOG_IF(WARNING, true) << "test: " << DebugString(); - -#ifdef MOZC_NO_LOGGING - EXPECT_EQ(g_counter, 0); -#else // MOZC_NO_LOGGING - EXPECT_EQ(g_counter, 3); -#endif // MOZC_NO_LOGGING - - g_counter = 0; - LOG_IF(INFO, false) << "test: " << DebugString(); - LOG_IF(ERROR, false) << "test: " << DebugString(); - LOG_IF(WARNING, false) << "test: " << DebugString(); - - EXPECT_EQ(g_counter, 0); -} - -struct StubStringify { - template - friend void AbslStringify(Sink &sink, const StubStringify &v) { - sink.Append(v.str); - } - - std::string str; -}; - -TEST(LoggingTest, AbslStringify) { - LOG(INFO) << "test: " << StubStringify{"testing info"}; - LOG(ERROR) << "test: " << StubStringify{"testing error"}; - LOG(WARNING) << "test: " << StubStringify{"testing warning"}; -} - -TEST(LoggingTest, WorkingLogStreamAsSink) { - WorkingLogStream stream; - stream.Append("hello"); - stream.Append(5, 'o'); - stream.Append(0, 'z'); - absl::Format(&stream, ", world"); - EXPECT_EQ(stream.str(), "helloooooo, world"); -} - -} // namespace -} // namespace mozc diff --git a/src/base/vlog.cc b/src/base/vlog.cc index 72aeb7223..ad26863e4 100644 --- a/src/base/vlog.cc +++ b/src/base/vlog.cc @@ -35,8 +35,19 @@ #include "absl/base/attributes.h" #include "absl/flags/flag.h" +// Note that abseil HEAD has ABSL_LTS_RELEASE_VERSION undefined. +#if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION >= 20240116 +#include "absl/flags/declare.h" +#include "absl/log/flags.h" // IWYU pragma: keep +#endif // ABSL_LTS_RELEASE_VERSION >= 20240116 +#if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION >= 20240116 +// Newer version of abseil defines --v flag. We rely on it to avoid symbol +// name collision (though not recommended). +ABSL_DECLARE_FLAG(int, v); +#else // ABSL_LTS_RELEASE_VERSION >= 20240116 ABSL_FLAG(int, v, 0, "Show all VLOG(m) messages for m <= this."); +#endif // ABSL_LTS_RELEASE_VERSION < 20240116 namespace mozc::internal { diff --git a/src/build_tools/test_tools/test_launcher.py b/src/build_tools/test_tools/test_launcher.py index eda435489..fc51c0817 100644 --- a/src/build_tools/test_tools/test_launcher.py +++ b/src/build_tools/test_tools/test_launcher.py @@ -36,8 +36,8 @@ The usage example is as follows. Sample Code: launcher = TestLauncher(gtest_report_dir='/tmp/my_gtest_report_dir') - launcher.AddTest(['/path/to/binary/some_test', '--logtostderr' ]) - launcher.AddTest(['/path/to/binary/another_test', '--logtostderr' ]) + launcher.AddTest(['/path/to/binary/some_test']) + launcher.AddTest(['/path/to/binary/another_test']) ... launcher.Execute(8) # Execute with specified number of processes. This function blocks main thread until all diff --git a/src/client/client.cc b/src/client/client.cc index 1f8948df4..c877db232 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -234,7 +234,6 @@ void Client::DumpHistorySnapshot(const absl::string_view filename, OutputFileStream output(snapshot_file, std::ios::app); output << "---- Start history snapshot for " << label << std::endl; - output << "Created at " << Logging::GetLogMessageHeader() << std::endl; output << "Version " << Version::GetMozcVersion() << std::endl; for (size_t i = 0; i < history_inputs_.size(); ++i) { output << absl::StrCat(history_inputs_[i]); diff --git a/src/client/client_stress_test_main.cc b/src/client/client_stress_test_main.cc index 4e2b92f0f..358d7d884 100644 --- a/src/client/client_stress_test_main.cc +++ b/src/client/client_stress_test_main.cc @@ -67,8 +67,6 @@ ABSL_FLAG(bool, test_testsendkey, true, "test TestSendKey"); int main(int argc, char **argv) { mozc::InitMozc(argv[0], &argc, &argv); - absl::SetFlag(&FLAGS_logtostderr, true); - mozc::client::Client client; if (!absl::GetFlag(FLAGS_server_path).empty()) { client.set_server_program(absl::GetFlag(FLAGS_server_path)); diff --git a/src/gyp/common.gypi b/src/gyp/common.gypi index 4d152d852..c4494b0e5 100644 --- a/src/gyp/common.gypi +++ b/src/gyp/common.gypi @@ -139,6 +139,7 @@ 'NDEBUG', 'QT_NO_DEBUG', 'MOZC_NO_LOGGING', + 'ABSL_MIN_LOG_LEVEL=100', 'IGNORE_HELP_FLAG', 'IGNORE_INVALID_FLAG' ], diff --git a/src/gyp/common_win.gypi b/src/gyp/common_win.gypi index 59e0af47f..7edee06a9 100644 --- a/src/gyp/common_win.gypi +++ b/src/gyp/common_win.gypi @@ -248,6 +248,7 @@ 'NDEBUG', 'QT_NO_DEBUG', 'MOZC_NO_LOGGING', + 'ABSL_MIN_LOG_LEVEL=100', 'IGNORE_HELP_FLAG', 'IGNORE_INVALID_FLAG' ], diff --git a/src/ios/ios_engine.cc b/src/ios/ios_engine.cc index d32ad14db..f2ab51a00 100644 --- a/src/ios/ios_engine.cc +++ b/src/ios/ios_engine.cc @@ -154,13 +154,6 @@ IosEngine::InputConfigTuple IosEngine::GetInputConfigTupleFromLayoutName( {Request::QWERTY_MOBILE_TO_HALFWIDTHASCII, commands::HALF_ASCII}}; } -void IosEngine::InitMozc() { - // Output logs to stderr so that they are displayed in XCode's console. - // This must be set before Logging::InitLogStream(). - absl::SetFlag(&FLAGS_logtostderr, true); - Logging::InitLogStream("MOZC_IOS_ENGINE"); -} - IosEngine::IosEngine(const std::string &data_file_path) : session_handler_(CreateSessionHandler(data_file_path)), session_id_(0), diff --git a/src/ios/ios_engine.h b/src/ios/ios_engine.h index 5ef7abc8f..3f18b0518 100644 --- a/src/ios/ios_engine.h +++ b/src/ios/ios_engine.h @@ -63,10 +63,6 @@ class IosEngine { ~IosEngine(); - // Initializes global modules. This function should be called before the - // initialization of IosEngine. - static void InitMozc(); - // The following methods are helpers to populate command proto and send it // to the session handler. Input to and output from the session handler are // recorded in |command|. The return value is the return value of diff --git a/src/ios/ios_engine_stub.cc b/src/ios/ios_engine_stub.cc index a3736d362..1b4bee2f5 100644 --- a/src/ios/ios_engine_stub.cc +++ b/src/ios/ios_engine_stub.cc @@ -41,10 +41,6 @@ class SessionHandlerInterface { namespace ios { -void IosEngine::InitMozc() { - // Do nothing. -} - IosEngine::IosEngine(const std::string &data_file_path) : session_handler_(new SessionHandlerInterface), session_id_(0) {} diff --git a/src/session/session_handler_main.cc b/src/session/session_handler_main.cc index c09359b0b..8d4303730 100644 --- a/src/session/session_handler_main.cc +++ b/src/session/session_handler_main.cc @@ -30,7 +30,7 @@ // session_handler_main.cc // // Usage: -// session_handler_main --logtostderr --input input.txt --profile /tmp/mozc +// session_handler_main --input input.txt --profile /tmp/mozc // --dictionary oss --engine desktop // /* Example of input.txt (tsv format) diff --git a/src/session/session_test.cc b/src/session/session_test.cc index 0b6e47b3d..83fb3729e 100644 --- a/src/session/session_test.cc +++ b/src/session/session_test.cc @@ -440,7 +440,9 @@ class SessionTest : public testing::TestWithTempUserProfile { constexpr uint32_t kNoModifiers = 0; auto chars_it = chars.begin(); for (const absl::string_view key : Utf8AsChars(key_strings)) { - CHECK_NE(chars_it, chars.end()); + // MSVC fails to compile if this is spelled as + // `CHECK_NE(chars_it, chars.end())`. + CHECK(chars_it != chars.end()); command->Clear(); command->mutable_input()->set_type(commands::Input::SEND_KEY); commands::KeyEvent *key_event = command->mutable_input()->mutable_key(); diff --git a/src/unix/ibus/BUILD.bazel b/src/unix/ibus/BUILD.bazel index 151526f2f..c81ac54db 100644 --- a/src/unix/ibus/BUILD.bazel +++ b/src/unix/ibus/BUILD.bazel @@ -280,7 +280,11 @@ mozc_cc_binary( "//unix:icons", ], defines = mozc_select( - linux = ["MOZC_NO_LOGGING"], + linux = [ + # TODO(komatsu): Define MOZC_NO_LOGGING properly in bazel build. + "MOZC_NO_LOGGING", + "ABSL_MIN_LOG_LEVEL=100", + ], oss_linux = [], ), deps = [ diff --git a/src/win32/tip/BUILD.bazel b/src/win32/tip/BUILD.bazel index 26c33b5be..017e53538 100644 --- a/src/win32/tip/BUILD.bazel +++ b/src/win32/tip/BUILD.bazel @@ -140,6 +140,7 @@ mozc_cc_library( ":tip_ui_handler", "//base:const", "//base:file_util", + "//base:log_file", "//base:logging", "//base:process", "//base:system_util", diff --git a/src/win32/tip/tip_text_service.cc b/src/win32/tip/tip_text_service.cc index 7b87ecd97..e328192c4 100644 --- a/src/win32/tip/tip_text_service.cc +++ b/src/win32/tip/tip_text_service.cc @@ -47,6 +47,7 @@ #include "absl/functional/any_invocable.h" #include "base/const.h" #include "base/file_util.h" +#include "base/log_file.h" #include "base/logging.h" #include "base/process.h" #include "base/system_util.h" @@ -509,7 +510,7 @@ class TipTextServiceImpl StorePointerForCurrentThread(this); HRESULT result = E_UNEXPECTED; - Logging::InitLogStream( + RegisterLogFileSink( FileUtil::JoinPath(SystemUtil::GetLoggingDirectory(), kLogFileName)); EnsureKanaLockUnlocked();