blob: 327276589074e548405bf7374aa30a417add6bc9 [file] [log] [blame]
// Copyright 2010-2015, 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_LOGGING_H_
#define MOZC_BASE_LOGGING_H_
#include <iostream>
#include <string>
#include "base/namespace.h"
#include "base/port.h"
namespace mozc {
enum LogSeverity {
#ifdef OS_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
LOG_INFO = 0,
LOG_WARNING = 1,
LOG_ERROR = 2,
// Special hack for Windows build, where ERROR is defined as 0 in wingdi.h.
#ifdef OS_WIN
LOG_0 = LOG_ERROR,
#endif // OS_WIN
LOG_FATAL = 3,
LOG_SEVERITY_SIZE = 4,
#endif
};
// DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef DEBUG
#define LOG_DFATAL LOG_FATAL
#else
#define LOG_DFATAL LOG_ERROR
#endif // DEBUG
class NullLogStream;
class Logging {
public:
// Initializes log stream. argv0 is the program name commonly
// storead as argv[0].
// The default log file is <USER_PROFILE>/<program_name>.log
static void InitLogStream(const char *argv0 = "UNKNOWN");
// Closes the logging stream
static void CloseLogStream();
// Gets logging stream. The log message can be written to the stream
static ostream &GetLogStream();
// Gets NullLogStream for 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 string GetLogMessageHeader();
// Returns FLAGS_v
static int GetVerboseLevel();
// Sets FLAGS_v
static void SetVerboseLevel(int verboselevel);
// Sets Verbose Level for Config.
// Since Config dialog will overwrite -v option, we separate
// config_verbose_level and FLAGS_v.
// real_config_level = max(FLAGS_v, config_verbose_level);
static void SetConfigVerboseLevel(int verboselevel);
// Gets an escape sequence to colorize log messages on tty devices.
static const char *GetBeginColorEscapeSequence(LogSeverity severity);
static const char *GetEndColorEscapeSequence();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Logging);
};
class LogFinalizer {
public:
explicit LogFinalizer(LogSeverity severity);
~LogFinalizer();
void operator&(ostream&);
private:
const LogSeverity severity_;
};
// When using NullLogStream, all debug message will be stripped
class NullLogStream {
public:
template <typename T>
NullLogStream& operator<<(const T &value) {
return *this;
}
NullLogStream& operator<<(ostream& (*pfunc)(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 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 // NO_LOGGING
#define LOG(severity) \
mozc::LogFinalizer(mozc::LOG_##severity) & mozc::Logging::GetLogStream() \
<< 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::GetLogStream() \
<< 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::GetLogStream() << mozc::Logging::GetLogMessageHeader() << " " \
<< __FILE__ << "(" << __LINE__ << ") " \
<< mozc::Logging::GetBeginColorEscapeSequence(mozc::LOG_FATAL) \
<< "CHECK" \
<< mozc::Logging::GetEndColorEscapeSequence() \
<< " [" << #condition << "] "
#endif // end NO_LOGGING
#define VLOG_IS_ON(verboselevel) \
(mozc::Logging::GetVerboseLevel() >= verboselevel)
#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel))
#define VLOG_IF(verboselevel, condition) \
LOG_IF(INFO, ((condition) && VLOG_IS_ON(verboselevel)))
#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 // DEBUG
#define DVLOG(verboselevel) DLOG_IF(INFO, VLOG_IS_ON(verboselevel))
#define DVLOG_IF(verboselevel, condition) \
DLOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel))
#endif // MOZC_BASE_LOGGING_H_