text: #include "caffe2/core/logging.h"
  
  #include <cstring>
  #include <numeric>
  
  #ifdef ANDROID
  #include <android/log.h>
  #endif  // ANDROID
  
  // Common code that we use regardless of whether we use glog or not.
  
  CAFFE2_DEFINE_bool(caffe2_use_fatal_for_enforce, false,
                     "If set true, when CAFFE_ENFORCE is not met, abort instead "
                     "of throwing an exception.");
  
  namespace caffe2 {
  std::string StripBasename(const std::string &full_path) {
    const char kSeparator = '/';
    size_t pos = full_path.rfind(kSeparator);
    if (pos != std::string::npos) {
      return full_path.substr(pos + 1, std::string::npos);
    } else {
      return full_path;
    }
  }
  
  size_t ReplaceAll(string& s, const char* from, const char* to) {
    CHECK(from && *from);
    CHECK(to);
  
    size_t numReplaced = 0;
    string::size_type lenFrom = std::strlen(from);
    string::size_type lenTo = std::strlen(to);
    for (string::size_type pos = s.find(from); pos != string::npos;
         pos = s.find(from, pos + lenTo)) {
      s.replace(pos, lenFrom, to);
      numReplaced++;
    }
    return numReplaced;
  }
  
  EnforceNotMet::EnforceNotMet(
      const char* file,
      const int line,
      const char* condition,
      const string& msg)
      : msg_stack_{MakeString(
            "[enforce fail at ",
            StripBasename(std::string(file)),
            ":",
            line,
            "] ",
            condition,
            ". ",
            msg)} {
    if (FLAGS_caffe2_use_fatal_for_enforce) {
      LOG(FATAL) << msg_stack_[0];
    } else {
      LOG(ERROR) << msg_stack_[0];
    }
  }
  
  void EnforceNotMet::AppendMessage(const string& msg) {
    LOG(ERROR) << msg;
    msg_stack_.push_back(msg);
  }
  
  string EnforceNotMet::msg() const {
    return std::accumulate(msg_stack_.begin(), msg_stack_.end(), string(""));
  }
  }  // namespace caffe2
  
  
  #ifdef CAFFE2_USE_GOOGLE_GLOG
  
  // GLOG's minloglevel
  DECLARE_int32(minloglevel);
  // GLOG's verbose log value.
  DECLARE_int32(v);
  
  CAFFE2_DEFINE_int(caffe2_log_level, google::ERROR,
                    "The minimum log level that caffe2 will output.");
  
  // Google glog's api does not have an external function that allows one to check
  // if glog is initialized or not. It does have an internal function - so we are
  // declaring it here. This is a hack but has been used by a bunch of others too
  // (e.g. Torch).
  namespace google {
  namespace glog_internal_namespace_ {
  bool IsGoogleLoggingInitialized();
  }  // namespace glog_internal_namespace_
  }  // namespace google
  
  
  namespace caffe2 {
  bool InitCaffeLogging(int* argc, char** argv) {
    if (*argc == 0) return true;
    if (!::google::glog_internal_namespace_::IsGoogleLoggingInitialized()) {
      ::google::InitGoogleLogging(argv[0]);
      ::google::InstallFailureSignalHandler();
    }
    // Transfer the caffe2_log_level setting to glog.
    FLAGS_minloglevel = FLAGS_caffe2_log_level;
    // Transfer the caffe2_log_level verbose setting to glog.
    if (FLAGS_caffe2_log_level < 0) {
      FLAGS_v = -FLAGS_caffe2_log_level;
    }
    return true;
  }
  }  // namespace caffe2
  
  #else  // !CAFFE2_USE_GOOGLE_GLOG
  
  CAFFE2_DEFINE_int(caffe2_log_level, ERROR,
                    "The minimum log level that caffe2 will output.");
  
  namespace caffe2 {
  bool InitCaffeLogging(int* argc, char** argv) {
    // When doing InitCaffeLogging, we will assume that caffe's flag paser has
    // already finished.
    if (*argc == 0) return true;
    if (!CommandLineFlagsHasBeenParsed()) {
      std::cerr << "InitCaffeLogging() has to be called after "
                   "ParseCaffeCommandLineFlags. Modify your program to make sure "
                   "of this." << std::endl;
      return false;
    }
    if (FLAGS_caffe2_log_level > FATAL) {
      std::cerr << "The log level of Caffe2 has to be no larger than FATAL("
                << FATAL << "). Capping it to FATAL." << std::endl;
      FLAGS_caffe2_log_level = FATAL;
    }
    return true;
  }
  
  MessageLogger::MessageLogger(const char *file, int line, int severity)
    : severity_(severity) {
    if (severity_ < FLAGS_caffe2_log_level) {
      // Nothing needs to be logged.
      return;
    }
  #ifdef ANDROID
    tag_ = "native";
  #else  // !ANDROID
    tag_ = "";
  #endif  // ANDROID
    /*
    time_t rawtime;
    struct tm * timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    std::chrono::nanoseconds ns =
        std::chrono::duration_cast<std::chrono::nanoseconds>(
            std::chrono::high_resolution_clock::now().time_since_epoch());
    */
    stream_ << "[" << CAFFE2_SEVERITY_PREFIX[std::min(4, FATAL - severity_)]
            //<< (timeinfo->tm_mon + 1) * 100 + timeinfo->tm_mday
            //<< std::setfill('0')
            //<< " " << std::setw(2) << timeinfo->tm_hour
            //<< ":" << std::setw(2) << timeinfo->tm_min
            //<< ":" << std::setw(2) << timeinfo->tm_sec
            //<< "." << std::setw(9) << ns.count() % 1000000000
            << " " << StripBasename(std::string(file)) << ":" << line << "] ";
  }
  
  // Output the contents of the stream to the proper channel on destruction.
  MessageLogger::~MessageLogger() {
    if (severity_ < FLAGS_caffe2_log_level) {
      // Nothing needs to be logged.
      return;
    }
    stream_ << "\n";
  #ifdef ANDROID
    static const int android_log_levels[] = {
        ANDROID_LOG_FATAL,    // LOG_FATAL
        ANDROID_LOG_ERROR,    // LOG_ERROR
        ANDROID_LOG_WARN,     // LOG_WARNING
        ANDROID_LOG_INFO,     // LOG_INFO
        ANDROID_LOG_DEBUG,    // VLOG(1)
        ANDROID_LOG_VERBOSE,  // VLOG(2) .. VLOG(N)
    };
    int android_level_index = FATAL - std::min(FATAL, severity_);
    int level = android_log_levels[std::min(android_level_index, 5)];
    // Output the log string the Android log at the appropriate level.
    __android_log_print(level, tag_, stream_.str().c_str());
    // Indicate termination if needed.
    if (severity_ == FATAL) {
      __android_log_print(ANDROID_LOG_FATAL, tag_, "terminating.\n");
    }
  #else  // !ANDROID
    if (severity_ >= FLAGS_caffe2_log_level) {
      // If not building on Android, log all output to std::cerr.
      std::cerr << stream_.str();
    }
  #endif  // ANDROID
    if (severity_ == FATAL) {
      DealWithFatal();
    }
  }
  
  }  // namespace caffe2
  
  #endif  // !CAFFE2_USE_GOOGLE_GLOG
  