mirror of
https://github.com/mii443/mozc.git
synced 2025-08-22 16:15:46 +00:00
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
This commit is contained in:
committed by
Hiroyuki Komatsu
parent
78aee2ace9
commit
c77285efa0
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -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',
|
||||
|
@ -104,7 +104,6 @@
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'container/bitarray_test.cc',
|
||||
'logging_test.cc',
|
||||
'mmap_test.cc',
|
||||
'random_test.h',
|
||||
'singleton_test.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
|
||||
|
71
src/base/log_file.cc
Normal file
71
src/base/log_file.cc
Normal file
@ -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 <string>
|
||||
|
||||
#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
|
44
src/base/log_file.h
Normal file
44
src/base/log_file.h
Normal file
@ -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 <string>
|
||||
|
||||
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_
|
@ -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 <android/log.h>
|
||||
#endif // __ANDROID__
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NO_MINMAX
|
||||
#include <windows.h>
|
||||
#else // _WIN32
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif // _WIN32
|
||||
|
||||
#include <algorithm>
|
||||
#ifdef _WIN32
|
||||
#include <codecvt>
|
||||
#endif // _WIN32
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#ifdef _WIN32
|
||||
#include <locale>
|
||||
#endif // _WIN32
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#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 <android/log.h>, 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<int>(mozc_log_level) == static_cast<int>(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<unsigned int>(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<uint64_t>(pthread_self()));
|
||||
#else // __LP64__
|
||||
return absl::StrCat(timestamp, ::getpid(), " ", ::getpid(),
|
||||
reinterpret_cast<uint32_t>(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<NullLogStream>::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<std::ostream> 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<char *>(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<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_to_wide;
|
||||
real_log_stream_ = std::make_unique<std::ofstream>(
|
||||
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<std::ofstream>(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<LogStreamImpl>::get()->Init(log_file_path);
|
||||
WorkingLogStream &stream = GetWorkingLogStream();
|
||||
stream << "Log file created at: " << Logging::GetLogMessageHeader();
|
||||
FinalizeWorkingLogStream(LogSeverity::LOG_INFO, &stream);
|
||||
}
|
||||
|
||||
void Logging::CloseLogStream() { Singleton<LogStreamImpl>::get()->Reset(); }
|
||||
|
||||
WorkingLogStream &Logging::GetWorkingLogStream() {
|
||||
return *(new WorkingLogStream);
|
||||
}
|
||||
|
||||
void Logging::FinalizeWorkingLogStream(LogSeverity severity,
|
||||
WorkingLogStream *working_stream) {
|
||||
*working_stream << std::endl;
|
||||
Singleton<LogStreamImpl>::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<NullLogStream>::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<LogStreamImpl>::get()->support_color()) {
|
||||
return kSeverityProperties[severity].color_escape_sequence;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *Logging::GetEndColorEscapeSequence() {
|
||||
if (Singleton<LogStreamImpl>::get()->support_color()) {
|
||||
return kClearEscapeSequence;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void Logging::SetLogToStderr(bool log_to_stderr) {
|
||||
Singleton<LogStreamImpl>::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
|
@ -30,335 +30,37 @@
|
||||
#ifndef MOZC_BASE_LOGGING_H_
|
||||
#define MOZC_BASE_LOGGING_H_
|
||||
|
||||
#include <string>
|
||||
// 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 <iostream>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#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 <android/log.h>
|
||||
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 <typename T, typename = void>
|
||||
struct HasAbslStringify : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct HasAbslStringify<
|
||||
T, std::void_t<decltype(AbslStringify(std::declval<WorkingLogStream &>(),
|
||||
std::declval<const T &>()))>>
|
||||
: 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 <typename T,
|
||||
std::enable_if_t<logging_internal::HasAbslStringify<T>::value,
|
||||
std::nullptr_t> = nullptr>
|
||||
WorkingLogStream &operator<<(const T &v) {
|
||||
AbslStringify(*this, v);
|
||||
return *this;
|
||||
}
|
||||
template <typename T,
|
||||
std::enable_if_t<!logging_internal::HasAbslStringify<T>::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 <typename T>
|
||||
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 <typename T>
|
||||
inline const absl::Status &AsStatus(const absl::StatusOr<T> &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_
|
||||
|
@ -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 <sstream>
|
||||
|
||||
#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 <typename Sink>
|
||||
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
|
@ -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 {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
@ -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));
|
||||
|
@ -139,6 +139,7 @@
|
||||
'NDEBUG',
|
||||
'QT_NO_DEBUG',
|
||||
'MOZC_NO_LOGGING',
|
||||
'ABSL_MIN_LOG_LEVEL=100',
|
||||
'IGNORE_HELP_FLAG',
|
||||
'IGNORE_INVALID_FLAG'
|
||||
],
|
||||
|
@ -248,6 +248,7 @@
|
||||
'NDEBUG',
|
||||
'QT_NO_DEBUG',
|
||||
'MOZC_NO_LOGGING',
|
||||
'ABSL_MIN_LOG_LEVEL=100',
|
||||
'IGNORE_HELP_FLAG',
|
||||
'IGNORE_INVALID_FLAG'
|
||||
],
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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 = [
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user